正题
题目链接:https://www.luogu.com.cn/problem/P5075
题目大意
mmm个糖分给AAA个小朋友,得到xxx个糖的小朋友可以贡献F(x)=Ox2+Sx+UF(x)=Ox^2+Sx+UF(x)=Ox2+Sx+U的贡献值。要求没有得到糖的小朋友一定是后面一段连续的序列,求所有方案的贡献值乘积之和。
解题思路
显然如果A>mA>mA>m那么后面的小朋友一定分不到糖,那么有A=min{A,m}A=min\{A,m\}A=min{A,m}
dpdpdp思路
设fi,jf_{i,j}fi,j表示iii个小朋友分了jjj个糖的贡献值之和
那么有fi,j=∑k=1jfi−1,j−k∗F(k)f_{i,j}=\sum_{k=1}^jf_{i-1,j-k}*F(k)fi,j=k=1∑jfi−1,j−k∗F(k)
发现这是一个卷积的形式,可以写为fi=fi−1∗Ff_{i}=f_{i-1}*Ffi=fi−1∗F,fn=f0∗Fnf_n=f_0*F^nfn=f0∗Fn
然后设gi,j=∑k=1ifk,jg_{i,j}=\sum_{k=1}^if_{k,j}gi,j=∑k=1ifk,j,那么答案就是gA,mg_{A,m}gA,m
然后优化转移gi,j=∑k=1i2fk,j+∑k=i2+1ifk,jg_{i,j}=\sum_{k=1}^{\frac{i}{2}}f_{k,j}+\sum_{k=\frac{i}{2}+1}^if_{k,j}gi,j=k=1∑2ifk,j+k=2i+1∑ifk,j
gi,j=gi2,j+∑k=1i2fk,j∗fi2,jg_{i,j}=g_{\frac{i}{2},j}+\sum_{k=1}^\frac{i}{2}f_{k,j}*f_{\frac{i}{2},j}gi,j=g2i,j+k=1∑2ifk,j∗f2i,j
卷积展开∑k=1i2fk,j∗fi2,j\sum_{k=1}^\frac{i}{2}f_{k,j}*f_{\frac{i}{2},j}∑k=12ifk,j∗f2i,j
gi,j=gi2,j+(∑k=1m−1fk,j)∗gi2,jg_{i,j}=g_{\frac{i}{2},j}+(\sum_{k=1}^{m-1}f_{k,j})*g_{\frac{i}{2},j}gi,j=g2i,j+(k=1∑m−1fk,j)∗g2i,j
gi=gi2+gi2∗fi2g_i=g_\frac{i}{2}+g_\frac{i}{2}*f_{\frac{i}{2}}gi=g2i+g2i∗f2i
然后FFTFFTFFT优化即可,时间复杂度O(mlog2m)O(m\log^2 m)O(mlog2m)
生成函数思路
设F(x)=∑k=0∞f(k)xkF(x)=\sum_{k=0}^\infty f(k)x^kF(x)=∑k=0∞f(k)xk
如果有kkk个人拿到糖那么就是(F(x)−1)k(F(x)-1)^k(F(x)−1)k
然后答案就是∑k=0A(F(x)−1)k\sum_{k=0}^A(F(x)-1)^kk=0∑A(F(x)−1)k
⇒1−(F(x)−1)A+12−F(x)\Rightarrow \frac{1-(F(x)-1)^{A+1}}{2-F(x)}⇒2−F(x)1−(F(x)−1)A+1
然后上多项式求逆和快速幂就好了
时间复杂度O(mlog2m)O(m\log^2 m)O(mlog2m)
当然我是fwfwfw所以写的是dpdpdp的代码
codecodecode
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define Pi acos(-1)
using namespace std;
const int N=40000;
struct complex{double x,y;complex(double xx=0,double yy=0){x=xx;y=yy;}
}ca[N],cb[N];
int n,m,P,A,O,S,U,r[N],tmp[N],f[N],g[N],pre[N];
complex operator+(complex a,complex b)
{return complex(a.x+b.x,a.y+b.y);}
complex operator-(complex a,complex b)
{return complex(a.x-b.x,a.y-b.y);}
complex operator*(complex a,complex b)
{return complex(a.x*b.x-a.y*b.y,a.x*b.y+a.y*b.x);}
void fft(complex *f,int op){for(int i=0;i<n;i++)if(i<r[i])swap(f[i],f[r[i]]);for(int p=2;p<=n;p<<=1){int len=p>>1;complex tmp(cos(Pi/len),sin(Pi/len)*op);for(int k=0;k<n;k+=p){complex buf(1,0);for(int i=k;i<k+len;i++){complex tt=buf*f[i+len];f[i+len]=f[i]-tt;f[i]=f[i]+tt;buf=buf*tmp;}}}return;
}
void mul(int *a,int *b,int *c){for(int i=0;i<n;i++)ca[i]=complex(a[i],0),cb[i]=complex(b[i],0);fft(ca,1);fft(cb,1);for(int i=0;i<n;i++)ca[i]=ca[i]*cb[i];fft(ca,-1);for(int i=1;i<=m;i++)c[i]=int((double)ca[i].x/n+0.5)%P;return;
}
void power(int b){if(b==1){memcpy(f,pre,sizeof(f));memcpy(g,pre,sizeof(g));return;}power(b>>1);mul(f,g,tmp);for(int i=0;i<n;i++)(g[i]+=tmp[i])%=P;mul(f,f,f);if(b&1){mul(f,pre,f);for(int i=0;i<n;i++)(g[i]+=f[i])%=P;}return;
}
int main()
{scanf("%d%d%d%d%d%d",&m,&P,&A,&O,&S,&U);for(int i=1;i<=m;i++)pre[i]=(O*i*i%P+S*i%P+U)%P;for(n=1;n<=m*2;n<<=1);for(int i=0;i<n;i++)r[i]=(r[i>>1]>>1)|((i&1)?n>>1:0);power(min(A,m));printf("%d",g[m]);return 0;
}