2016vijos 1-3 兔子的晚会(生成函数+倍增FWT)
求出序列的生成函数后,倍增FWT
#include<cstdio> using namespace std; #define N 2048 const int mod=1e9+7; int inv; int f[N+1]; int Pow(int a,int b) { int res=1; for(;b;a=1LL*a*a%mod,b>>=1) if(b&1) res=1LL*res*a%mod; return res; } void FWT(int *a,int n) { int x,y; for(int d=1;d<n;d<<=1) for(int m=d<<1,i=0;i<n;i+=m) for(int j=0;j<d;++j) { x=a[i+j]; y=a[i+j+d]; a[i+j]=x+y; a[i+j+d]=x-y; a[i+j]-=a[i+j]>=mod ? mod : 0; a[i+j+d]+=a[i+j+d]<0 ? mod : 0; } } void IFWT(int *a,int n) { int x,y; for(int d=1;d<n;d<<=1) for(int m=d<<1,i=0;i<n;i+=m) for(int j=0;j<d;++j) { x=a[i+j]; y=a[i+j+d]; a[i+j]=1LL*(x+y)*inv%mod; a[i+j+d]=1LL*(x-y+mod)%mod*inv%mod; } } int main() { //freopen("xor.in","r",stdin); //freopen("xor.out","w",stdout); int n,m,L,R; scanf("%d%d%d%d",&n,&m,&L,&R); n=2*n+1; inv=Pow(2,mod-2); int len; int ans=0; for(int x=L;x<=R;++x) { len=1; while(len<=x+m) len<<=1; for(int i=0;i<x;++i) f[i]=0; for(int i=x;i<=x+m;++i) f[i]=1; for(int i=x+m+1;i<len;++i) f[i]=0; FWT(f,len); for(int i=0;i<len;++i) f[i]=Pow(f[i],n); IFWT(f,len); ans+=f[0]; ans-=ans>=mod ? mod : 0; } printf("%d",ans); }