自己是有多么sb。

密钥

大家都说这是一道普及-的题,一年前我做不起,我可以说我太弱啦,我就普及组水平,今年我还是做不起……

看大佬题解都是:开个桶就好啦!

我:你在说什么……

首先把环拉成链,倍长。

如果确定$i$这个位置是起始位置,那么特征值就是$\sum\limits_{j=1}^{n-1} (p_j!=0 , sum(A_{i+1}...A_{i+j})>0) $。

那么我们先记录一个前缀和,后面所提到的$A$都是前缀和。$\sum\limits_{j=1}^{n-1} (p_j!=0 , A_{i+j} > A_{i})$。

我们可以这样来考虑,我们把$A$看作高度,从左到右连起来看成折线,我每次在$A_{i}$高度处拉根线,比线高的,并且向上走的(就是p!=0),的折线的个数就是特征值

因为$A_i-A_{i-1}$要么是1要么是-1,所以我们每次减掉或者加上某一个取值的个数就可以了,所以这就是开个桶的意义。

然后如果$p!=0$是B的位置的时候,如果图不变,相当于比线低的,往下走的,的折线的个数,就是特征值,

然后因为折线起始点和终止点的高度都是拉的这根线的高度,

所以比线低的,往下走的,和比线低或者相等的,往上走的,是可以一一对应的,数目是相等的,

而比线低或者相等的,往上走的个数,就是k-比线高的,并且向上走的个数

我在说啥……

  1. //Serene
  2. #include<algorithm>
  3. #include<iostream>
  4. #include<cstring>
  5. #include<cstdlib>
  6. #include<cstdio>
  7. #include<cmath>
  8. using namespace std;
  9. #define ll long long
  10. #define db double
  11. #define For(i,a,b) for(int i=(a);i<=(b);++i)
  12. #define Rep(i,a,b) for(int i=(a);i>=(b);--i)
  13. const int maxn=4e7+7;
  14. int n,k,seed,now,S,p[maxn],cnt[maxn],A[maxn],ans1,ans2,ans3;
  15.  
  16. char cc; ll ff;
  17. template<typename T>void read(T& aa) {
  18. aa=0;cc=getchar();ff=1;
  19. while((cc<'0'||cc>'9')&&cc!='-') cc=getchar();
  20. if(cc=='-') ff=-1,cc=getchar();
  21. while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
  22. aa*=ff;
  23. }
  24.  
  25. int getrand(){
  26. seed = ((seed * 12321) ^ 9999) % 32768;
  27. return seed;
  28. }
  29.  
  30. void generateData(){
  31. scanf("%d%d%d",&k,&seed,&S);
  32. int t = 0;
  33. n = k * 2 + 1;
  34. memset(p, 0, sizeof(p));
  35. for (int i = 1; i <= n; i++)
  36. {
  37. p[i] = (getrand() / 128) % 2;
  38. t += p[i];
  39. }
  40. int i = 1;
  41. while (t > k)
  42. {
  43. while (p[i] == 0)
  44. i++;
  45. p[i] = 0;
  46. t--;
  47. }
  48. while (t < k)
  49. {
  50. while (p[i] == 1)
  51. i++;
  52. p[i] = 1;
  53. t++;
  54. }
  55. }
  56.  
  57. int main() {
  58. generateData();
  59. For(i,1,n) p[i+n]=p[i];
  60. A[0]=n+1; For(i,1,n<<1) A[i]=A[i-1]+(p[i]? 1:-1);
  61. For(i,1,n) if(p[i]) ++cnt[A[i]],now+=A[i]>A[0];
  62. For(i,1,n) {
  63. if(p[i]) {
  64. now-=cnt[A[i]];//from A[i]-1 to A[i]
  65. --cnt[A[i]];
  66. ++cnt[A[i+n]];
  67. now+=A[i+n]>A[i];
  68. }
  69. else {
  70. now+=cnt[A[i]+1];//from A[i]+1 to A[i]
  71. if(now==0) ans1=i;
  72. if(now==S) ans2=i;
  73. if(now==k-S) ans3=i;
  74. }
  75. }
  76. printf("%d\n%d\n%d\n",ans1,ans2,ans3);
  77. return 0;
  78. }

吉夫特

想了很久,还是只会n^2暴力,翻开洛谷题解:

what? 众所周知,只有我不知道?

知道这玩意就可以直接每次枚举子集啦,洛谷上是可以过的,但是bz上就要T掉啦。

  1. //Serene
  2. #include<algorithm>
  3. #include<iostream>
  4. #include<cstring>
  5. #include<cstdlib>
  6. #include<cstdio>
  7. #include<cmath>
  8. using namespace std;
  9. #define ll long long
  10. #define db double
  11. #define For(i,a,b) for(int i=(a);i<=(b);++i)
  12. #define Rep(i,a,b) for(int i=(a);i>=(b);--i)
  13. const int maxn=3e5+7;
  14. ll mod=1e9+7;
  15. ll n,a[maxn],p[maxn],dp[maxn];
  16.  
  17. char cc; ll ff;
  18. template<typename T>void read(T& aa) {
  19. aa=0;cc=getchar();ff=1;
  20. while((cc<'0'||cc>'9')&&cc!='-') cc=getchar();
  21. if(cc=='-') ff=-1,cc=getchar();
  22. while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
  23. aa*=ff;
  24. }
  25.  
  26. int main() {
  27. read(n);
  28. For(i,1,n) read(a[i]),p[a[i]]=i;
  29. For(i,1,n) {
  30. dp[0]+=dp[i]%=mod;
  31. for(int j=a[i];j;j=(j-1)&a[i])
  32. if(p[j]>i) dp[p[j]]+=dp[i]+1;
  33. }
  34. printf("%lld\n",dp[0]%mod);
  35. return 0;
  36. }

所以应该怎么办呢

我们如果枚举子集复杂度大约是3^18的,但是如果我们把18位分成两半,各9位,然后一个是求答案时枚举补集,一个是更新dp数组,枚举子集,就优秀多了

具体意思见代码

  1. //Serene
  2. #include<algorithm>
  3. #include<iostream>
  4. #include<cstring>
  5. #include<cstdlib>
  6. #include<cstdio>
  7. #include<cmath>
  8. using namespace std;
  9. #define ll long long
  10. #define db double
  11. #define For(i,a,b) for(int i=(a);i<=(b);++i)
  12. #define Rep(i,a,b) for(int i=(a);i>=(b);--i)
  13. const int maxn=3e5+7,maxt=(1<<9)+7,U=(1<<9)-1;
  14. ll mod=1e9+7;
  15. ll n,o,x,y,dp[maxt][maxt],ans,now;
  16.  
  17. char cc; ll ff;
  18. template<typename T>void read(T& aa) {
  19. aa=0;cc=getchar();ff=1;
  20. while((cc<'0'||cc>'9')&&cc!='-') cc=getchar();
  21. if(cc=='-') ff=-1,cc=getchar();
  22. while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
  23. aa*=ff;
  24. }
  25.  
  26. void mo(ll& x) {if(x>=mod) x-=mod;}
  27.  
  28. int main() {
  29. read(n);
  30. For(i,1,n) {
  31. read(o); x=o>>9; y=o&U; now=0;
  32. for(int j=x;j<=U;j=(j+1)|x) now+=dp[j][y];
  33. now%=mod; ans+=now; now++; mo(now);
  34. for(int j=y;;j=(j-1)&y) {
  35. dp[x][j]+=now,mo(dp[x][j]);
  36. if(j==0) break;
  37. }
  38. }
  39. printf("%lld\n",ans%mod);
  40. return 0;
  41. }

CTSC2017密钥、吉夫特的更多相关文章

  1. bzoj 4900 [CTSC2017]密钥 模拟+乱搞

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4900 #include<cstring> #include<cmath&g ...

  2. 【BZOJ4903】【CTSC2017】吉夫特 [DP]

    吉夫特 Time Limit: 15 Sec  Memory Limit: 512 MB[Submit][Status][Discuss] Description Input 第一行一个整数n. 接下 ...

  3. 【LOJ】#2264. 「CTSC2017」吉夫特

    题解 根据一番认真严肃的猜结论和打表证明之后 我们可以得到 \(f[i] = (\sum_{a[i] \& a[j] == a[j]} f[j]) + 1\) 统计所有的\(f[i] - 1\ ...

  4. 【BZOJ4903/UOJ300】【CTSC2017】吉夫特

    Description 传送门 ​ 简述题意:给一个序列,询问有多少子序列满足其中不会出现\(a\choose b\)是偶数的情况,其中\(a\)在\(b\)前面. Solution 首先探究组合数的 ...

  5. bzoj4900 [CTSC2017]密钥

    传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=4900 [题解] 恭喜bzoj达到40页 考场由于傻逼基数排序写挂了而gg. 竟然忘了考试前一 ...

  6. [CTSC2017]密钥

    传送门:http://uoj.ac/problem/297 “无论哪场比赛,都要相信题目是水的” 这不仅是HNOI2018D2T3的教训,也是这题的教训,思维定势真的很可怕. 普及组水题,真是愧对CT ...

  7. [CTSC2017][bzoj4903] 吉夫特 [状压dp+Lucas定理]

    题面 传送门 思路 一句话题意: 给出一个长度为 n 的序列,求所有长度大于等于2的子序列个数,满足:对于子序列中任意两个相邻的数 a和 b (b 在 a 前面),$C_a^b mod 2=1$,答案 ...

  8. uoj#300.【CTSC2017】吉夫特

    题面:http://uoj.ac/problem/300 一道大水题,然而我并不知道$lucas$定理的推论.. $\binom{n}{m}$为奇数的充要条件是$n&m=n$.那么我们对于每个 ...

  9. Noip前的大抱佛脚----赛前任务

    赛前任务 tags:任务清单 前言 现在xzy太弱了,而且他最近越来越弱了,天天被爆踩,天天被爆踩 题单不会在作业部落发布,所以可(yi)能(ding)会不及时更新 省选前的练习莫名其妙地成为了Noi ...

随机推荐

  1. iOS开发CATransform3D.h属性详解和方法使用

    1.CATransform3D简介 layer有个属性transform,是CATransform3D类型.可以使其在三维界面作平移.缩放和旋转单独或组合动画! CATransform3D结构体: / ...

  2. C语言实现 计算个人所得税务2种方法

    #include <stdio.h> #include <stdlib.h> /* 基于C语言的个人所得税计税系统 问题描述: 我国现行的个人所得税计算方法如下: 级数 全月应 ...

  3. elasticDump的安装使用

    官方地址:官方地址:https://github.com/taskrabbit/elasticsearch-dump 安装方式如下:安装NodeJS下载源码:wget http://nodejs.or ...

  4. 设置和修改Linux的swap分区大小

    在Linux编译gcc时,遇到编译错误,究其根源是因为内存不足,这时通过修改swap大小解决了问题 相关操作如下: 1. 查看当前分区情况free -m 2. 增加 swap 大小, 2G 左右dd ...

  5. nprogress 转

    转载:http://www.xuanfengge.com/front-end-nprogress-and-lightweight-web-progress-bar-nanobar.html 前言 进度 ...

  6. bzoj1003物流运输 最短路+DP

    bzoj1003物流运输 题目描述 物流公司要把一批货物从码头A运到码头B.由于货物量比较大,需要n天才能运完.货物运输过程中一般要转停好几个码头.物流公司通常会设计一条固定的运输路线,以便对整个运输 ...

  7. 微信小程序多商品评价评星提交

    <form bindsubmit="submitComment"> <block wx:for="{{commentList}}" wx:ke ...

  8. SQLServer:目录

    ylbtech-SQLServer:目录 1.返回顶部   2. 文档返回顶部 · https://docs.microsoft.com/zh-cn/sql/sql-server/sql-server ...

  9. 原 ASP.net out 和ref之间的区别

    ref和out都是C#中的关键字,所实现的功能也差不多,都是指定一个参数按照引用传递.对于编译后的程序而言,它们之间没有任何区别,也就是说它们只有语法区别.总结起来,他们有如下语法区别: 1.ref传 ...

  10. 使用em为单位制作两列弹性布局

    一.DIV布局按照定位的方法分为:浮动方法(float),坐标定位方法(position),还有就是两者相结合的方法. 二.DIV布局按照定义单位的不同可分为:固定宽度布局.流体布局.弹性布局和混合布 ...