BZOJ 3992 [SDOI2015]序列统计
题解:求m的原根,把乘法转化成加法,然后用NTT加速动态规划
听说这是循环卷积???并不会啊,留个坑。
NTT连板子都不熟
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=1000009;
typedef long long Lint;
const Lint mm2=1004535809;
int n,m,fin,mm;
Lint g;
int ref[maxn];
void Getg(){
for(g=2;g<mm;++g){
Lint tmp=1;
int fla=1;
for(int i=1;i<mm-1;++i){
tmp=tmp*g%mm;
if(tmp==1){
fla=0;break;
}
}
if(fla)break;
}
Lint tmp=1;ref[1]=0;
for(int i=1;i<mm-1;++i){
tmp=tmp*g%mm;
ref[tmp]=i;
}
}
Lint Ksm(Lint a,Lint p){
Lint ret=1;
for(;p;p>>=1,a=a*a%mm2){
if(p&1)ret=ret*a%mm2;
}
return ret;
}
Lint a[maxn];
Lint b[maxn];
Lint ret[maxn];
int l,rev[maxn];
void NTT(Lint *a,int f,int n){
for(int i=0;i<n;++i)if(i<rev[i])swap(a[i],a[rev[i]]);
for(int i=1;i<n;i<<=1){
int p=i+i;
Lint wn=Ksm(3,mm2/p);
if(f==-1)wn=Ksm(wn,mm2-2);
for(int j=0;j<n;j+=p){
Lint w=1;
for(int k=0;k<i;++k,w=w*wn%mm2){
Lint x=a[j+k],y=a[j+k+i]*w%mm2;
a[j+k]=(x+y)%mm2;a[j+k+i]=(x-y+mm2)%mm2;
}
}
}
if(f==-1){
Lint inv=Ksm(n,mm2-2);
for(int i=0;i<n;++i)a[i]=a[i]*inv%mm2;
}
}
void Getans(int p){
m=mm+mm-4;
int n;
for(n=1;n<=m;n<<=1)l++;
for(int i=0;i<n;++i)rev[i]=(rev[i>>1]>>1)|((i&1)<<(l-1));
ret[0]=1;
for(;p;p>>=1){
if(p&1){
for(int i=0;i<n;++i)b[i]=a[i];
NTT(ret,1,n);NTT(b,1,n);
for(int i=0;i<n;++i)ret[i]=ret[i]*b[i]%mm2;
NTT(ret,-1,n);
for(int i=mm-1;i<n;++i){
ret[i%(mm-1)]+=ret[i];ret[i]=0;
}
for(int i=0;i<mm-1;++i)ret[i]%=mm2;
}
for(int i=0;i<n;++i)b[i]=a[i];
NTT(a,1,n);NTT(b,1,n);
for(int i=0;i<n;++i)a[i]=a[i]*b[i]%mm2;
NTT(a,-1,n);
for(int i=mm-1;i<n;++i){
a[i%(mm-1)]+=a[i];a[i]=0;
}
for(int i=0;i<mm-1;++i)a[i]%=mm2;
// for(int i=0;i<n;++i)cout<<a[i]<<' ';
// cout<<endl;
}
}
int main(){
scanf("%d%d%d%d",&n,&mm,&fin,&m);
Getg();
while(m--){
int x;scanf("%d",&x);
if(x!=0)a[ref[x]]++;
}
Getans(n);
printf("%lld\n",ret[ref[fin]]%mm2);
return 0;
}
致歉:笔者已经意识到这是一篇几乎没有价值的文章,给您的阅读带来不好的体验,并且干扰了您的搜索环境,非常抱歉!

浙公网安备 33010602011771号