CF623E Transforming Sequence

题目描述:

luogu

CF

题解:

任意模数$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;
}
View Code
原文地址:https://www.cnblogs.com/LiGuanlin1124/p/10975795.html