4332: JSOI2012 分零食

Time Limit: 10 Sec  Memory Limit: 256 MB
Submit: 119  Solved: 66

Description

这里是欢乐的进香河,这里是欢乐的幼儿园。 
今天是2月14日,星期二。在这个特殊的日子里,老师带着同学们欢乐地跳着,笑着。校长从幼儿园旁边的小吃店买了大量的零食决定分给同学们。听到这个消息,所有同学都安安静静地排好了队,大家都知道,校长不喜欢调皮的孩子。 
同学们依次排成了一列,其中有A位小朋友,有三个共同的欢乐系数O,S和U。如果有一位小朋友得到了x个糖果,那么她的欢乐程度就是f(x)=O*x2+S*x+U。 
现在校长开始分糖果了,一共有M个糖果。有些小朋友可能得不到糖果,对于那些得不到糖果的小朋友来说,欢乐程度就是1。如果一位小朋友得不到糖果,那么在她身后的小朋友们也都得不到糖果。(即这一列得不到糖果的小朋友一定是最后的连续若干位) 
所有分糖果的方案都是等概率的。现在问题是:期望情况下,所有小朋友的欢乐程度的乘积是多少?呆呆同学很快就有了一个思路,只要知道总的方案个数T和所有方案下欢乐程度乘积的总和S,就可以得到答案Ans=S/T。现在他已经求出来了T的答案,但是S怎么求呢?他就不知道了。你能告诉他么? 
因为答案很大,你只需要告诉他S对P取模后的结果。 
后记: 
虽然大家都知道,即便知道了T,知道了S对P取模后的结果,也没有办法知道期望情况下,所有小朋友欢乐程度的乘积。但是,当呆呆想到这一点的时候,已经彻底绝望了。 

Input

第一行有2个整数,分别是M和P。 
第二行有一个整数A,第三行有一个整数O。 
第四行有一个整数S,第五行有一个整数U。 

Output

一个整数S,因为答案可能很大,你只需要输出S 对P取模后的结果。 

Sample Input

4 100
4
1
0
0

Sample Output

63

样例说明
函数f(x)=x^2。一共有4份零食,4位同学。如果只有第一个同学得到,欢乐程度为16,若前两位同学得到,欢乐程度的所有可能依次为9,9,16,若有三位同学得到,欢乐程度有4,4,4,最后一种情况,每一个同学都得到了零食,欢乐程度为1。相加后得到S=63。

应上传者要求,此题不公开,如有异议,请提出.

HINT

对于100%的数据,M<=10000,P<=255,A<=108,O<=4,S<=300,U<=100。

Source

【分析】


O(n^2)做法:【实测可以过全部

  1. #include<cstdio>
  2. #include<cstdlib>
  3. #include<cstring>
  4. #include<iostream>
  5. #include<algorithm>
  6. using namespace std;
  7. int Mod;
  8. int f[][];
  9.  
  10. int main()
  11. {
  12. int m,n,a,b,c;
  13. scanf("%d%d%d%d%d%d",&m,&Mod,&n,&a,&b,&c);
  14. if(n>m) n=m;
  15. memset(f,,sizeof(f));
  16. f[][]=;
  17. int ans=,p=,ss;
  18. for(int j=;j<=n;j++)
  19. {
  20. int nw=,pp=p^;
  21. memset(f[pp],,sizeof(f[pp]));
  22. ss=;
  23. for(int i=;i<=m;i++)
  24. {
  25. if(i>=) ss=(ss+f[p][i-])%Mod;
  26. f[pp][i]=f[pp][i-];
  27. if(i>=) nw=(nw+ss**a)%Mod;
  28. if(i>=) nw=(nw+f[p][i-]*(*a+a+b))%Mod;
  29. f[pp][i]=(f[pp][i]+nw+f[p][i-]*(a+b+c))%Mod;
  30. }p^=;
  31. ans=(ans+f[p][m])%Mod;
  32. }
  33. printf("%d\n",ans);
  34. return ;
  35. }

具体解释见这里


O(n^2 logn)

【实测还不如暴力,不知道是不是我常数大。

【就是后面两个for改成卷积形式

  1. #include<cstdio>
  2. #include<cstdlib>
  3. #include<cstring>
  4. #include<iostream>
  5. #include<algorithm>
  6. #include<cmath>
  7. using namespace std;
  8. const double pi=acos(-);
  9. #define Maxn 10010*4
  10. int Mod;
  11. int f[Maxn],g[Maxn];
  12.  
  13. struct P
  14. {
  15. double x,y;
  16. P() {x=y=;}
  17. P(double x,double y):x(x),y(y){}
  18. friend P operator + (P x,P y) {return P(x.x+y.x,x.y+y.y);}
  19. friend P operator - (P x,P y) {return P(x.x-y.x,x.y-y.y);}
  20. friend P operator * (P x,P y) {return P(x.x*y.x-x.y*y.y,x.x*y.y+x.y*y.x);}
  21. }a[Maxn],b[Maxn];
  22.  
  23. int R[Maxn],nn,m;
  24. void dft(P *a,int t)
  25. {
  26. for(int i=;i<=nn;i++) if(i<R[i]) swap(a[i],a[R[i]]);
  27. for(int i=;i<nn;i<<=)
  28. {
  29. P wn(cos(pi/i),t*sin(pi/i));
  30. for(int j=;j<nn;j+=(i<<))
  31. {
  32. P w(,);
  33. for(int k=;k<i;k++,w=w*wn)
  34. {
  35. P x=a[j+k],y=w*a[j+k+i];
  36. a[j+k]=x+y;a[j+k+i]=x-y;
  37. }
  38. }
  39. }
  40. if(t==-)
  41. {
  42. for(int i=;i<=nn;i++) a[i].x/=nn;
  43. }
  44. }
  45.  
  46. void fft(int *X,int *Y)
  47. {
  48. for(int i=;i<=nn;i++)
  49. {
  50. a[i].x=X[i];a[i].y=;
  51. b[i].x=Y[i];b[i].y=;
  52. }
  53. dft(a,);dft(b,);
  54. for(int i=;i<=nn;i++) a[i]=a[i]*b[i];
  55. dft(a,-);
  56. for(int i=;i<=m;i++) X[i]=(int)(a[i].x+0.5)%Mod;
  57. }
  58.  
  59. int main()
  60. {
  61. int n,a,b,c;
  62. scanf("%d%d%d%d%d%d",&m,&Mod,&n,&a,&b,&c);
  63. if(n>m) n=m;
  64. f[]=g[]=;
  65. for(int i=;i<=m;i++) f[i]=g[i]=(a*i*i+b*i+c)%Mod;
  66. int ans=; ans+=f[m];
  67.  
  68. nn=;int ll=;
  69. while(nn<=*m) nn<<=,ll++;
  70. for(int i=;i<=nn;i++) R[i]=(R[i>>]>>)|((i&)<<(ll-));
  71. for(int i=;i<=n;i++)
  72. {
  73. fft(f,g);
  74. ans=(ans+f[m])%Mod;
  75. }
  76. printf("%d\n",ans);
  77. return ;
  78. }

O(nlogn^2)做法:

把上面的第一个循环改成快速幂

从7点搞到了现在。。

  理解奥爷爷的代码好久啊。。。但是打的真心短。。。

  下面那个qpow是一个矩阵乘法的快速幂!!【我傻啊看了很久才看出来。。

  所以求$G^1+G^2+...G^n$

呵呵【我看这个看了好久

【呵呵

其实我觉得这个卷积有点迷

但是不管了,明天再说

关于$a^1+a^2+a^3...+a^n$,当然如果你只是要求数的话,可以直接套等比数列求和公式。但如果不是数呢?或者mod下没有逆元怎么求分母呢?

可以用 矩阵乘法快速幂 ,就类似上面的那个方法的。

打成数值的形式是这样:

  1. #include<cstdio>
  2. #include<cstdlib>
  3. #include<cstring>
  4. #include<iostream>
  5. #include<algorithm>
  6. using namespace std;
  7.  
  8. int main()
  9. {
  10. int x,y;
  11. scanf("%d%d",&x,&y);
  12. int ans=,xx=x;
  13. while(y)
  14. {
  15. if(y&)
  16. {
  17. ans=ans*x+xx*;
  18. }
  19. xx=xx*x+xx*;
  20. x=x*x;
  21. y>>=;
  22. }
  23. printf("%d\n",ans);
  24. }

上面的求卷积的幂的和,就是这样子做的。

然后是O(n logn^2)的代码

  1. #include<cstdio>
  2. #include<cstdlib>
  3. #include<cstring>
  4. #include<iostream>
  5. #include<algorithm>
  6. #include<cmath>
  7. using namespace std;
  8. #define Maxn 10010*4
  9. const double pi=acos(-);
  10. int Mod;
  11.  
  12. struct P
  13. {
  14. double x,y;
  15. P() {x=y=;}
  16. P(double x,double y):x(x),y(y){}
  17. friend P operator + (P x,P y) {return P(x.x+y.x,x.y+y.y);}
  18. friend P operator - (P x,P y) {return P(x.x-y.x,x.y-y.y);}
  19. friend P operator * (P x,P y) {return P(x.x*y.x-x.y*y.y,x.x*y.y+x.y*y.x);}
  20. }a[Maxn],b[Maxn];
  21.  
  22. int R[Maxn],nn,m;
  23. void dft(P *a,int f)
  24. {
  25. for(int i=;i<nn;i++) if(i<R[i]) swap(a[i],a[R[i]]);
  26. for(int i=;i<nn;i<<=)
  27. {
  28. P wn(cos(pi/i),f*sin(pi/i));
  29. for(int j=;j<nn;j+=i<<)
  30. {
  31. P w(,);
  32. for(int k=;k<i;k++,w=w*wn)
  33. {
  34. P x=a[j+k],y=w*a[j+k+i];
  35. a[j+k]=x+y;a[j+k+i]=x-y;
  36. }
  37. }
  38. }
  39. if(f==-)
  40. {
  41. for(int i=;i<=nn;i++) a[i].x/=nn,a[i].y/=nn;
  42. }
  43. }
  44.  
  45. int A[Maxn],B[Maxn],C[Maxn],nw[Maxn];
  46. int aa,bb,cc;
  47. void fft(int *A,int *B)
  48. {
  49. for(int i=;i<nn;i++)
  50. {
  51. a[i].x=A[i];a[i].y=;
  52. b[i].x=B[i];b[i].y=;
  53. }
  54. dft(a,);dft(b,);
  55. for(int i=;i<=nn;i++) a[i]=a[i]*b[i];
  56. dft(a,-);
  57. for(int i=;i<=m;i++) A[i]=((int)(a[i].x+0.5)%Mod);
  58. }
  59.  
  60. void add(int *A,int *B)
  61. {
  62. for(int i=;i<=m;i++) A[i]=(A[i]+B[i])%Mod;
  63. }
  64.  
  65. void qpow(int k)
  66. {
  67. for(int i=;i<=m;i++) A[i]=;
  68. for(int i=;i<=m;i++) C[i]=B[i]=(aa*i*i+bb*i+cc)%Mod;
  69. while(k)
  70. {
  71. if(k&)
  72. {
  73. fft(A,B);
  74. add(A,C);
  75. }
  76. for(int i=;i<=m;i++) nw[i]=C[i];
  77. fft(C,B);
  78. add(C,nw);
  79. fft(B,B);
  80. k>>=;
  81. }
  82. }
  83.  
  84. int main()
  85. {
  86. int n;
  87. scanf("%d%d%d%d%d%d",&m,&Mod,&n,&aa,&bb,&cc);
  88. if(n>m) n=m;
  89. nn=;int ll=;
  90. while(nn<=*m) nn<<=,ll++;
  91. for(int i=;i<=nn;i++) R[i]=(R[i>>]>>)|((i&)<<(ll-));
  92. qpow(n);
  93. printf("%d\n",A[m]);
  94. return ;
  95. }

2017-04-14 21:46:24

【BZOJ 4332】 4332: JSOI2012 分零食 (FFT+快速幂)的更多相关文章

  1. bzoj 4332:JSOI2012 分零食

    描述 这里是欢乐的进香河,这里是欢乐的幼儿园. 今天是2月14日,星期二.在这个特殊的日子里,老师带着同学们欢乐地跳着,笑着.校长从幼儿园旁边的小吃店买了大量的零食决定分给同学们.听到这个消息,所有同 ...

  2. BZOJ 4332: JSOI2012 分零食 FFT+分治

    好题好题~ #include <bits/stdc++.h> #define N 50020 #define ll long long #define setIO(s) freopen(s ...

  3. [BZOJ 4332] [JSOI2012]分零食(DP+FFT)

    [BZOJ 4332] [JSOI2012]分零食(DP+FFT) 题面 同学们依次排成了一列,其中有A位小朋友,有三个共同的欢乐系数O,S和U.如果有一位小朋友得到了x个糖果,那么她的欢乐程度就是\ ...

  4. BZOJ 3160: 万径人踪灭 FFT+快速幂+manacher

    BZOJ 3160: 万径人踪灭 题目传送门 [题目大意] 给定一个长度为n的01串,求有多少个回文子序列? 回文子序列是指从原串中找出任意个,使得构成一个回文串,并且位置也是沿某一对称轴对称. 假如 ...

  5. 【codeforces 623E】dp+FFT+快速幂

    题目大意:用$[1,2^k-1]$之间的证书构造一个长度为$n$的序列$a_i$,令$b_i=a_1\ or\ a_2\ or\ ...\ or a_i$,问使得b序列严格递增的方案数,答案对$10^ ...

  6. BZOJ 3329 Xorequ:数位dp + 矩阵快速幂

    传送门 题意 现有如下方程:$ x \oplus 3x = 2x $ 其中 $ \oplus $ 表示按位异或. 共 $ T $ 组数据,每组数据给定正整数 $ n $,任务如下: 求出小于等于 $ ...

  7. P3321 [SDOI2015]序列统计 FFT+快速幂+原根

    \(\color{#0066ff}{ 题目描述 }\) 小C有一个集合S,里面的元素都是小于M的非负整数.他用程序编写了一个数列生成器,可以生成一个长度为N的数列,数列中的每个数都属于集合S.小C用这 ...

  8. [BZOJ 1297][SCOI 2009]迷路(矩阵快速幂)

    题目:http://www.lydsy.com:808/JudgeOnline/problem.php?id=1297 分析:如果每条边的边权都是1,那么就相当于对邻接矩阵自乘T次(因为写一下递推式子 ...

  9. BZOJ 1009: [HNOI2008]GT考试( dp + 矩阵快速幂 + kmp )

    写了一个早上...就因为把长度为m的也算进去了... dp(i, j)表示准考证号前i个字符匹配了不吉利数字前j个的方案数. kmp预处理, 然后对于j进行枚举, 对数字0~9也枚举算出f(i, j) ...

随机推荐

  1. Java 9 中的 9 个新特性

    Java 8 发布三年多之后,java9已经发布了 . 你可能已经听说过 Java 9 的模块系统,但是这个新版本还有许多其它的更新. 这里有九个令人兴奋的新功能将与 Java 9 一起发布.   1 ...

  2. 推箱子 BFS

    [编程题] 推箱子 大家一定玩过“推箱子”这个经典的游戏.具体规则就是在一个N*M的地图上,有1个玩家.1个箱子.1个目的地以及若干障碍,其余是空地.玩家可以往上下左右4个方向移动,但是不能移动出地图 ...

  3. Impala笔记之通用命令

    help help命令用于查询其它命令的用法 [quickstart.cloudera:21000] > help select; Executes a SELECT... query, fet ...

  4. [整理] magento搬家

    将原来网站文件中的var文件中的cache和session文件删除,将media中的缓存文件删除.然后将所有文件制作成一个压缩包,以减少文件体积,方便转移. 将压缩包转移到新的服务器域名指向的文件夹, ...

  5. Verilog笔记.5.同步、异步

    在数字电路中经常有同步synchronism.异步asynchronism的概念.异步指输入信号和时钟无关:同步指输入信号和时钟信号有关,实际上就是输入信号和时钟信号进行了与运算或者与非运算.实际开发 ...

  6. 巅峰极客第二场CTF部分writeup

    word-MISC 微信回答问题+word字体里. sqli-WEB 注册个admin空格即可,长字符截断. 晚上把后续的写出来.现在睡觉

  7. 关于SQLite3 编译及交叉编译的一些问题

    from : http://blog.sina.com.cn/s/blog_5f2e119b0101ibwn.html SQLite3 (http://www.sqlite.org)是一个非常强大的小 ...

  8. linux wc命令的作用。

    Linux系统中的wc(Word Count)命令的功能为统计指定文件中的字节数.字数.行数,并将统计结果显示输出. 1.命令格式: wc [选项]文件... 2.命令功能: 统计指定文件中的字节数. ...

  9. ansible 下lineinfile详细使用 【转】

    转自 ansible 下lineinfile详细使用 - 散人 - 51CTO技术博客http://zouqingyun.blog.51cto.com/782246/1882367 一.简述 这几天在 ...

  10. 123.Best Time to Buy and Sell Stock III---dp

    题目链接:https://leetcode.com/problems/best-time-to-buy-and-sell-stock-iii/description/ 题目大意:与122题类似,只是这 ...