首页 > 代码库 > 【BZOJ 4332】 4332: JSOI2012 分零食 (FFT+快速幂)
【BZOJ 4332】 4332: JSOI2012 分零食 (FFT+快速幂)
4332: JSOI2012 分零食
Time Limit: 10 Sec Memory Limit: 256 MB
Submit: 119 Solved: 66Description
这里是欢乐的进香河,这里是欢乐的幼儿园。今天是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
0Sample 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
【分析】
从7点搞到了现在。。
理解奥爷爷的代码好久啊。。。但是打的真心短。。。
下面那个qpow是一个矩阵乘法的快速幂!!【我傻啊看了很久才看出来。。
所以求$G^1+G^2+...G^n$
呵呵【我看这个看了好久
【呵呵
其实我觉得这个卷积有点迷
但是不管了,明天再说
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(-1); 10 int Mod; 11 12 struct P 13 { 14 double x,y; 15 P() {x=y=0;} 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=0;i<nn;i++) if(i<R[i]) swap(a[i],a[R[i]]); 26 for(int i=1;i<nn;i<<=1) 27 { 28 P wn(cos(pi/i),f*sin(pi/i)); 29 for(int j=0;j<nn;j+=i<<1) 30 { 31 P w(1,0); 32 for(int k=0;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==-1) 40 { 41 for(int i=0;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=0;i<nn;i++) 50 { 51 a[i].x=A[i];a[i].y=0; 52 b[i].x=B[i];b[i].y=0; 53 } 54 dft(a,1);dft(b,1); 55 for(int i=0;i<=nn;i++) a[i]=a[i]*b[i]; 56 dft(a,-1); 57 for(int i=1;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=1;i<=m;i++) A[i]=(A[i]+B[i])%Mod; 63 } 64 65 void qpow(int k) 66 { 67 for(int i=0;i<=m;i++) A[i]=0; 68 for(int i=1;i<=m;i++) C[i]=B[i]=(aa*i*i+bb*i+cc)%Mod; 69 while(k) 70 { 71 if(k&1) 72 { 73 fft(A,B); 74 add(A,C); 75 } 76 for(int i=1;i<=m;i++) nw[i]=C[i]; 77 fft(C,B); 78 add(C,nw); 79 fft(B,B); 80 k>>=1; 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=1;int ll=0; 90 while(nn<=2*m) nn<<=1,ll++; 91 for(int i=0;i<=nn;i++) R[i]=(R[i>>1]>>1)|((i&1)<<(ll-1)); 92 qpow(n); 93 printf("%d\n",A[m]); 94 return 0; 95 }
2017-04-14 21:46:24
【BZOJ 4332】 4332: JSOI2012 分零食 (FFT+快速幂)
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。