bzoj 4332:JSOI2012 分零食


  

描述

這里是歡樂的進香河,這里是歡樂的幼兒園。

今天是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 }

 


注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
  © 2014-2022 ITdaan.com 联系我们: