描述
這里是歡樂的進香河,這里是歡樂的幼兒園。
今天是2月14日,星期二。在這個特殊的日子里,老師帶著同學們歡樂地跳著,笑著。校長從幼兒園旁邊的小吃店買了大量的零食決定分給同學們。聽到這個消息,所有同學都安安靜靜地排好了隊,大家都知道,校長不喜歡調皮的孩子。
同學們依次排成了一列,其中有A位小朋友,有三個共同的歡樂系數O,S和U。如果有一位小朋友得到了x個糖果,那么她的歡樂程度就是f(x)=Ox^2+Sx+U。
現在校長開始分糖果了,一共有M個糖果。有些小朋友可能得不到糖果,對于那些得不到糖果的小朋友來說,歡樂程度就是1。如果一位小朋友得不到糖果,那么在她身后的小朋友們也都得不到糖果。(即這一列得不到糖果的小朋友一定是最后的連續若干位)
所有分糖果的方案都是等概率的。現在問題是:期望情況下,所有小朋友的歡樂程度的乘積是多少?呆呆同學很快就有了一個思路,只要知道總的方案個數T和所有方案下歡樂程度乘積的總和S,就可以得到答案Ans=S/T。現在他已經求出來了T的答案,但是S怎么求呢?他就不知道了。你能告訴他么?
因為答案很大,你只需要告訴他S對P取模后的結果。
后記:
雖然大家都知道,即便知道了T,知道了S對P取模后的結果,也沒有辦法知道期望情況下,所有小朋友歡樂程度的乘積。但是,當呆呆想到這一點的時候,已經徹底絕望了。
格式
輸入格式
第一行有2個整數,分別是M和P。
第二行有一個整數A,第三行有一個整數O。
第四行有一個整數S,第五行有一個整數U。
輸出格式
一個整數S,因為答案可能很大,你只需要輸出S 對P取模后的結果。
?
看到很多大佬虐這道題,我也很好奇就寫了寫。
題里直接給了個生成函數$c$和一個卷積的形式$c^x$,如果題里沒有要求拿到糖的人是一個前綴的話直接令$c[0]=1$求一發多項式快速冪就行了。
但有了限制之后,考慮枚舉得到糖的人數,因為不能有人沒有糖,令$c[0]=0$。
設$f[i]$表示只有i個糖時的答案,最后答案為$f[m]$,則
$$f=\sum_{i=1}^{A}c^i$$
感覺如果模數合適的話應該可以等比數列求和直接做吧。。。開始還以為是一道水題
但顯然這道題不行,那就考慮倍增。
設$g[i]=c^{2^i},sumg[i]=\sum_{i=1}^{2^i}c^i$
把$A$二進制拆分后用上邊兩個數組顯然是可以求出來的,懶得寫了。。。
注意FFT完往回賦值時只賦$0-m$,不要把FFT完的整個數組都賦回去,調了一晚上不知道哪錯了。。。
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 #include<cmath> 6 #define pi acos(-1) 7 #define N 50005 8 #define double long double 9 using namespace std; 10 struct E 11 { 12 double x,y; 13 E(){;} 14 E(double _x,double _y) 15 { 16 x=_x;y=_y; 17 } 18 friend E operator + (E a,E b) 19 { 20 return E(a.x+b.x,a.y+b.y); 21 } 22 friend E operator - (E a,E b) 23 { 24 return E(a.x-b.x,a.y-b.y); 25 } 26 friend E operator / (E a,double b) 27 { 28 return E(a.x/b,a.y/b); 29 } 30 friend E operator * (E a,E b) 31 { 32 return E(a.x*b.x-a.y*b.y,a.x*b.y+a.y*b.x); 33 } 34 }a[N],b[N]; 35 int R[N],n; 36 void fft(E *a,int f) 37 { 38 for(int i=0;i<n;i++)if(i<R[i])swap(a[i],a[R[i]]); 39 for(int i=1;i<n;i<<=1) 40 { 41 E wn(cos(pi/i),f*sin(pi/i)); 42 for(int j=0;j<n;j+=(i<<1)) 43 { 44 E w(1,0); 45 for(int k=0;k<i;k++,w=w*wn) 46 { 47 E x=a[j+k],y=w*a[j+k+i]; 48 a[j+k]=x+y;a[j+k+i]=x-y; 49 } 50 } 51 } 52 if(f==-1) 53 { 54 for(int i=0;i<n;i++)a[i]=a[i]/(double)n; 55 } 56 return ; 57 } 58 int m,p,A,O,S,U; 59 int c[N]; 60 int g[15][N],sg[15][N]; 61 void make(int *a1,int *a2,int *a3) 62 { 63 for(int i=0;i<n;i++)a[i].x=a[i].y=b[i].x=b[i].y=0; 64 for(int i=0;i<n;i++)a[i].x+=a2[i]; 65 for(int i=0;i<n;i++)b[i].x+=a3[i]; 66 fft(a,1);fft(b,1); 67 for(int i=0;i<n;i++)a[i]=a[i]*b[i]; 68 fft(a,-1); 69 for(int i=0;i<=m;i++)a1[i]=(int)(a[i].x+0.2); 70 for(int i=0;i<=m;i++)a1[i]%=p; 71 } 72 int gg[N]; 73 void solve() 74 { 75 for(int i=0;i<n;i++)g[0][i]=c[i]; 76 for(int i=1;i<=13;i++)make(g[i],g[i-1],g[i-1]); 77 for(int i=0;i<n;i++)sg[0][i]=c[i]; 78 for(int i=1;i<=13;i++) 79 { 80 for(int j=0;j<n;j++)sg[i][j]=sg[i-1][j]; 81 make(gg,sg[i-1],g[i-1]); 82 for(int j=0;j<n;j++) 83 { 84 sg[i][j]=sg[i][j]+gg[j]; 85 if(sg[i][j]>=p)sg[i][j]-=p; 86 } 87 } 88 return ; 89 } 90 int ans[N],now[N]; 91 void pw(int y) 92 { 93 now[0]=1; 94 for(int i=13;i>=0;i--) 95 { 96 if(y&(1<<i)) 97 { 98 make(gg,now,sg[i]); 99 make(now,now,g[i]); 100 for(int j=0;j<n;j++) 101 { 102 ans[j]=ans[j]+gg[j]; 103 if(ans[j]>=p)ans[j]-=p; 104 } 105 } 106 } 107 return ; 108 } 109 int main() 110 { 111 scanf("%d%d%d%d%d%d",&m,&p,&A,&O,&S,&U); 112 S%=p;O%=p;U%=p; 113 for(int i=1;i<=m;i++)c[i]=(1LL*O*i*i%p+1LL*S*i%p+U)%p; 114 n=1;int l=0; 115 while(n<=2*m)n<<=1,l++; 116 for(int i=0;i<n;i++)R[i]=(R[i>>1]>>1)|((i&1)<<(l-1)); 117 if(A>m)A=m; 118 solve(); 119 pw(A); 120 printf("%d\n",ans[m]); 121 return 0; 122 }
?