题目描述:
题解:
任意模数$ntt$/奇技淫巧$fft$。
首先设$f[i][j]$表示在第$i$轮每种有$j$个“1”的01串有$f[i][j]$种生成方式。
所以答案=$sum f[n][i]*C(k,i)$。
顺便提一下,$n>k$时$puts("0")$即可。
然后有这个方程:$$f[x][i]=sum_{j=0}^{i-1}f[x-1][j]*2^j*C(i,j)$$
拓展一下:$$f[x+y][i] = sum _{j=0} ^{i-1} f[ x ][ j ] * f[ y ][ i-j ]*2 ^ {y*j} * C(i,j)$$
化成$ntt$形式:$$frac{f[ x+y ][ i ]}{ i! } = sum _{j=0} ^{i-1} frac{f[ x ][ j ] * 2^{y*j} }{ j! } * frac{ 1 }{ (i-j)! }$$
然后就可以任意模数$ntt$了。
(或者下面的奇技淫巧$fft$)
代码:
#include<cmath> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; typedef long long ll; const long double Pi = acos(-1.0); const int MOD = 1000000007; const int N = 130050; template<typename T> inline void read(T&x) { T f = 1,c = 0;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){c=c*10+ch-'0';ch=getchar();} x = f*c; } ll fastpow(ll x,ll y) { ll ret = 1; while(y) { if(y&1)ret=ret*x%MOD; x=x*x%MOD; y>>=1; } return ret; } ll inv(ll x){return fastpow(x,MOD-2);} ll n,ny[N],jc[N],jny[N],M[N]; int m; struct cp { long double x,y; cp(){} cp(long double x,long double y):x(x),y(y){} cp operator + (const cp&a)const{return cp(x+a.x,y+a.y);} cp operator - (const cp&a)const{return cp(x-a.x,y-a.y);} cp operator * (const cp&a)const{return cp(x*a.x-y*a.y,x*a.y+y*a.x);} }; int to[N],lim,L; void init() { lim = 1,L = 0; while(lim<=(2*m))lim<<=1,L++; for(int i=1;i<lim;i++)to[i] = ((to[i>>1]>>1)|((i&1)<<(L-1))); M[0] = ny[1] = jc[0] = jc[1] = jny[0] = jny[1] = 1; M[1] = 2; for(int i=2;i<=m;i++) { ny[i] = ((MOD - MOD/i) * ny[MOD%i] %MOD+MOD )%MOD; jc[i] = (jc[i-1] * i)%MOD; jny[i] = (jny[i-1] * ny[i])%MOD; M[i] = (M[i-1] * 2)%MOD; } } ll C(ll x,ll y){return jc[x]*jny[y]%MOD*jny[x-y]%MOD;} void fft(cp*a,int len,int k) { for(int i=0;i<len;i++) if(i>to[i])swap(a[i],a[to[i]]); for(int i=1;i<len;i<<=1) { cp w0(cos(Pi/i),k*sin(Pi/i)); for(int j=0;j<len;j+=(i<<1)) { cp w(1,0); for(int o=0;o<i;o++,w=w*w0) { cp w1 = a[j+o],w2 = a[j+o+i]*w; a[j+o] = w1+w2; a[j+o+i] = w1-w2; } } } if(k==-1) for(int i=0;i<len;i++)a[i].x/=len; } ll F[N],G[N],H[N]; cp a[N],b[N],c[N],d[N],e[N],f[N],g[N],h[N]; void mul(ll y) { ll K = fastpow(2,y),KK = 1,M = 32768; for(int i=0;i<lim;i++)a[i]=b[i]=c[i]=d[i]=cp(0,0); for(int i=0;i<=m;i++) { ll A = G[i]*KK%MOD,B = H[i]; a[i].x = A/M,b[i].x = A%M; c[i].x = B/M,d[i].x = B%M; KK = KK*K%MOD; } fft(a,lim,1),fft(b,lim,1),fft(c,lim,1),fft(d,lim,1); for(int i=0;i<lim;i++) { e[i]=a[i]*c[i],f[i]=b[i]*c[i]; g[i]=a[i]*d[i],h[i]=b[i]*d[i]; } fft(e,lim,-1),fft(f,lim,-1),fft(g,lim,-1),fft(h,lim,-1); for(int i=0;i<lim;i++) F[i] = (((ll)(e[i].x+0.1))%MOD*M%MOD*M%MOD + ((ll)(f[i].x+0.1))%MOD*M%MOD + ((ll)(g[i].x+0.1))%MOD*M%MOD + ((ll)(h[i].x+0.1))%MOD)%MOD; } ll o[N],s[N]; void FastFFT() { ll y = 1; for(int i=1;i<=m;i++)o[i]=jny[i]; s[0] = 1; ll N = n; while(N) { if(N&1) { memcpy(G,s,sizeof(G)); memcpy(H,o,sizeof(H)); mul(y); memcpy(s,F,sizeof(s)); } memcpy(G,o,sizeof(G)); memcpy(H,o,sizeof(H)); mul(y); memcpy(o,F,sizeof(o)); y<<=1,N>>=1; } } int main() { read(n),read(m); init(); if(n>m) { puts("0"); return 0; } FastFFT(); ll ans = 0; for(int i=n;i<=m;i++) (ans+=s[i]*C(m,i)%MOD*jc[i]%MOD)%=MOD; printf("%lld ",ans); return 0; }