BZOJ3456:城市规划

我中间有一步没开LongLong,然后快速幂的时候就GG了
大概就是:

f(n)ng(n)ng(n)=2n(n1)21g(n)=i=1nC(n1,i1)f(i)g(ni)西(1004535809)g(n)=i=1n(n1)!f(i)g(ni)(i1)!(ni)!(n1)!g(n)(n1)!=i=1nf(i)(i1)!g(ni)(ni)!qwqA,B,CA=BCB=ACCA f ( n ) 代 表 n 个 点 的 无 向 连 通 图 数 目 g ( n ) 代 表 n 个 点 的 无 向 图 数 目 g ( n ) = 2 n ( n − 1 ) 2 考 虑 枚 举 1 个 点 所 在 连 通 块 的 点 的 个 数 g ( n ) = ∑ i = 1 n C ( n − 1 , i − 1 ) ∗ f ( i ) ∗ g ( n − i ) 这 东 西 是 不 是 长 得 很 像 卷 积 ( 明 明 是 1004535809 像 卷 积 ) 然 后 我 们 把 组 合 数 拆 开 之 后 : g ( n ) = ∑ i = 1 n ( n − 1 ) ! f ( i ) g ( n − i ) ( i − 1 ) ! ( n − i ) ! 两 边 同 时 除 以 ( n − 1 ) ! g ( n ) ( n − 1 ) ! = ∑ i = 1 n f ( i ) ( i − 1 ) ! ∗ g ( n − i ) ( n − i ) ! 这 样 就 变 成 卷 积 了 q w q 然 后 设 这 三 部 分 分 别 为 A , B , C 那 么 有 : A = B ∗ C 那 么 B = A C 那 么 C 求 个 逆 元 , 然 后 乘 上 A 就 好 了

代码:

#include
#include
#include
#include
#include
#include
#define LL long long
using namespace std;
inline int read(){
    int x=0,f=1;char ch=' ';
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
    return x*f;
}
const int N=5e5+5,mod=1004535809,g=3,gi=334845270;
inline LL ksm(LL a,LL n){
    LL ans=1LL;
    while(n){
        if(n&1)ans=ans*a%mod;
        a=a*a%mod;
        n>>=1;
    }
    return ans;
}
int n,R[N],m,bin[1<<23];
LL f[N],ans[N],h[N],tmp[N],inv_h[N],fac[N],inv[N],ifac[N],C[N];
inline void NTT(LL *a,int n,int f){
    int L=bin[n];
    for(int i=0;i>1]>>1)|((i&1)<<(L-1));
    for(int i=0;iif(ifor(int i=1;i1){
        LL wn=ksm(f==1?g:gi,(mod-1)/(i<<1));
        for(int j=0;j1)){
            LL w=1LL;
            for(int k=0;kif(f==-1)for(int i=0;i2)%mod;
}
inline void poly_inv(LL *a,LL *b,int n){
    if(n==1){b[0]=ksm(a[0],mod-2);return;}
    poly_inv(a,b,(n+1)>>1);
    int m=1;
    for(;m<(n<<1);m<<=1);
    for(int i=0;ifor(int i=n;i0;
    NTT(tmp,m,1);NTT(b,m,1);
    for(int i=0;i2LL*b[i]%mod-tmp[i]*b[i]%mod*b[i]%mod+mod)%mod;
    NTT(b,m,-1);
    for(int i=n;i0;
    return;
}
int main(){
    for(int i=0;i<22;++i)bin[1<0]=ifac[0]=inv[0]=inv[1]=1;
    for(int i=1;i<=n;++i)fac[i]=fac[i-1]*i%mod;
    for(int i=2;i<=n;++i)inv[i]=(mod-mod/i)*inv[mod%i]%mod;
    for(int i=1;i<=n;++i)ifac[i]=ifac[i-1]*inv[i]%mod;
    for(int i=1;i<=n;++i)C[i]=(LL)i*(i-1)/2%(mod-1);
    for(int i=1;i<=n;++i)f[i]=ksm(2LL,C[i])*ifac[i-1]%mod;
    for(int i=0;i<=n;++i)h[i]=ksm(2LL,C[i])*ifac[i]%mod;
    for(m=1;m<=n;m<<=1);
    poly_inv(h,inv_h,n+1);
    NTT(f,m,1);NTT(inv_h,m,1);
    for(int i=0;i1);
    printf("%lld",ans[n]*fac[n-1]%mod);
    return 0;
}

你可能感兴趣的:(只会板子的FFT,DP真的不会想,生成函数好像并不遥远)