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

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

### 分析

$dp[i][j]$表示i个人里分j个零食得到的答案

$s_n=\sum_{i=1}^n dp_i$

$=s_{\frac{n}{2}}+f^{\frac{n}{2}}*\sum_{i=1}^{\frac{n}{2}} f^{i}$

$s_n=s_{\frac{n}{2}}+dp_{\frac{n}{2}}*s_{\frac{n}{2}}$

### 代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<complex>
#define maxn 300000
#include<cmath>
using namespace std;
typedef complex<double> com;
typedef long long ll;
const double pi=acos(-1.0);

int n,m;
ll O,S,U;
ll mod;
void fft(com *x,int *rev,int n,int type){
for(int i=0;i<n;i++) if(i<rev[i]) swap(x[i],x[rev[i]]);
for(int len=1;len<n;len*=2){
int sz=len*2;
com wn1=com(cos(2*pi/sz),type*sin(2*pi/sz));
for(int l=0;l<n;l+=sz){
int r=l+len-1;
com wnk=com(1,0);
for(int i=l;i<=r;i++){
com tmp=x[i+len];
x[i+len]=x[i]-tmp*wnk;
x[i]=x[i]+tmp*wnk;
wnk*=wn1;
}
}
}
}

struct poly{
int len;
ll arr[maxn+5];
inline int size(){
return len;
}
inline ll & operator [](int i){
return arr[i];
}
friend void operator += (poly &p,poly &q){
for(int i=0;i<=p.len;i++){
p.arr[i]=(p.arr[i]+q.arr[i])%mod;
}
}
void print(){
for(int i=0;i<=len;i++) printf("%d ",arr[i]);
printf("\n");
}
};
int rev[maxn+5];
com tmpa[maxn+5],tmpb[maxn+5],tmpc[maxn+5];
void mul(poly &a,poly &b,poly &c){

int tn=1,k=0;
while(tn<=a.len*2){
k++;
tn*=2;
}
for(int i=0;i<tn;i++){
rev[i]=(rev[i>>1]>>1)|((i&1)<<(k-1));
tmpa[i]=tmpb[i]=tmpc[i]=0;
}
for(int i=0;i<=a.len;i++){
tmpa[i]=a[i];
tmpb[i]=b[i];
}
fft(tmpa,rev,tn,1);
fft(tmpb,rev,tn,1);
for(int i=0;i<tn;i++) tmpc[i]=tmpa[i]*tmpb[i];
fft(tmpc,rev,tn,-1);
for(int i=0;i<=a.len;i++) c[i]=(ll)(tmpc[i].real()/tn+0.5)%mod;
}

poly f,g,tmp,a;
inline void fast_pow(int k){
if(k==1){
f.len=g.len=m;
tmp.len=m;
for(int i=0;i<=m;i++) f[i]=g[i]=a[i];
return;
}
fast_pow(k>>1);
//	f.print();
//	g.print();
mul(f,g,tmp);
//	tmp.print();
f+=tmp;
mul(g,g,g);
if(k&1){
mul(g,a,g);
f+=g;
}
}

inline ll calc(ll x){
return O*x*x%mod+S*x%mod+U%mod;
}
int main(){
scanf("%d %lld",&m,&mod);
scanf("%d %lld %lld %lld",&n,&O,&S,&U);
for(int i=1;i<=m;i++) a[i]=calc(i)%mod;
//注意a[0]=0,而不是calc(0)，因为分到0的快乐度是1，对答案无影响，不用累加
fast_pow(n);
printf("%lld\n",f[m]);
}



posted @ 2019-08-29 22:00  birchtree  阅读(240)  评论(0编辑  收藏  举报