• BZOJ 3456 城市规划 ( NTT + 多项式求逆 )


    题目链接:

    https://www.lydsy.com/JudgeOnline/problem.php?id=3456

    题意:

    求出(n)个点的简单(无重边无自环)无向连通图的个数。((n<=130000)).

    并且输出方案数mod (1004535809(479 * 2 ^ {21} + 1)).

    题解:

    这题是POJ 1737的加强版。

    从之前写过的题解中:

    POJ 1737 Connected Graph

    我们知道存在这样的递推式:

    $$f[n]=2^{C(n,2)}-sum_{i=1}^{n-1}f[i]C(n-1,i-1)2^{C(n-i,2)}$$

    将上式左右两边同除以((n−1)!)得到:

    $$frac{f[n]}{(n−1)!}=frac{2^{C(n,2)}}{(n−1)!} - frac{sum_{i=1}^{n-1}f[i]C(n-1,i-1)2^{C(n-i,2)}}{(n−1)!}$$

    $$implies frac{f[n]}{(n−1)!}=frac{2^{C(n,2)}}{(n−1)!} - sum_{i=1}^{n-1}frac{f[i]2^{C(n-i,2)}}{(i-1)!(n-i)!}$$

    $$implies frac{2^{C(n,2)}}{(n−1)!}=sum_{i=1}^{n}frac{f[i]2^{C(n-i,2)}}{(i-1)!(n-i)!} $$

    $$implies sum_{i=1}^{n}frac{f[i]}{(i-1)!}*frac{2^{C(n-i,2)}}{(n-i)!} = frac{2^{C(n,2)}}{(n−1)!} $$

    这个显然是一个卷积的形式。

    指数级生成函数。

    那么我们可以令:

    $$A = sum_{i=1}^{n}frac{f[i]}{(i-1)!}x^i$$

    $$B = sum_{i=0}^{n}frac{2^{C(i,2)}}{i!}x^i$$

    $$C = sum_{i=1}^{n}frac{2^{C(i,2)}}{(i−1)!}x^i$$

    有:

    $$A*B = C$$

    那么有:

    $$A≡C*B^{-1}(mod x^{n+1})$$

    先预处理(B)(C),再用多项式求逆得到(B)的逆,再跑个NTT就可以了。

    复杂度:(O(nlogn)).

    代码:

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int maxn = 1e6 + 10;
    const int maxLen = 18, maxm = 1 << maxLen | 1;
    const ll maxv = 1e10 + 6; // 1e14, 1e15
    const int N = 1000000;
    const long double pi = acos(-1.0); // double maybe is not enough
    ll mod = 1004535809, nlim, sp, msk;
    
    ll qpower(ll x, ll p) { // x ^ p % mod
    	ll ret = 1;
    	while (p) {
    		if (p & 1) (ret *= x) %=mod;
    		(x *= x) %=mod; 
    		p >>= 1;
    	}
    	return ret;
    }
    int R[N];
    int G = 3;
    void NTT(int *a,int f,int n,int L)
    {
        for(int i = 0;i < n; i++) {
    		R[i] = (R[i>>1]>>1)|((i&1)<<(L-1));
    	}
        for(int i = 0;i < n;i++) {
            if(i < R[i]) swap(a[i],a[R[i]]);
    	}
        for(int i = 1;i < n;i <<= 1) 
        {
            int wn = qpower(G,(mod-1)/(i<<1));
            if(f==-1) wn = qpower(wn,mod-2);
            for(int j = 0;j < n;j += (i<<1))
    		{
                int w=1;
                for(int k = 0; k < i; k++,w = 1LL * w * wn % mod)
    			{
                    int x=a[j+k];
    				int y=1LL*a[j+k+i]*w%mod;
                    a[j+k]=(x+y)%mod;
                    a[j+k+i]=(x-y+mod)%mod;
                }
            }
        }
        if(f==-1){
            int tmp = qpower(n,mod-2);
            for(int i = 0;i < n;i++) 
            {
    			a[i] = 1LL * a[i] * tmp % mod;
    		}
        }
    }
    int d[N];
    void ployInv(int *a,int *b,int n,int L){
        if(n == 1){
            b[0] = qpower(a[0],mod - 2);return;
        }
        ployInv(a,b,n >> 1,L - 1);
        memcpy(d,a,n*sizeof(int));
        memset(d + n,0,n*sizeof(int));
        NTT(d,1,n << 1,L + 1);
    	NTT(b,1,n << 1,L + 1);
        for(int i = 0;i < (n<<1); i++)  {
    		b[i] = 1LL * b[i] * ((2LL - 1LL * d[i] * b[i] % mod + mod) % mod) % mod;
    	}
        NTT(b,-1,n << 1,L + 1);
        memset(b + n,0,n * sizeof(int));
    }
    ll n,m;
    ll fac[N];
    int L;
    int A[N],B[N],C[N],inv_B[N];
    int main()
    {
    	// freopen("in.txt","r",stdin);
      	std::cin >> n;
    	m = 1;
    	while(m <= (n << 1)) m<<=1, L++;
    
    	fac[0] = 1;
    	for(int i = 1; i <= n; i++) {
    		fac[i] = fac[i-1] * i % mod;
    	}
    	for(ll i = 0; i <= n; i++) {
    		B[i] = qpower(2,(i * (i - 1)>>1)) * qpower(fac[i],mod - 2) % mod;
    	}
    
    	for(ll i = 1; i <= n; i++) {
    		C[i] = qpower(2,(i * (i - 1)>>1)) * qpower(fac[i - 1],mod - 2) % mod;
    	}
    
    	A[0] = 1;
    	ployInv(B,inv_B,m,L);
    	NTT(inv_B,1,m,L);
    	NTT(C,1,m,L);
    	for(int i = 0; i < m; i++) {
    		A[i] = 1LL * inv_B[i] * C[i] % mod;
    	}
    	NTT(A,-1,m,L);
    	std::cout << A[n] * fac[n-1] % mod << '
    ';
      	return 0;
    }
    
    
  • 相关阅读:
    fopen & fcolse & fseek & ftell & fstat 文件操作函数测试
    python基础练习题30道
    2636652995 揭秘骗子qq
    python的异常处理try/except 万能处理exception
    类的装饰器的基本原理
    描述符的应用
    描述符
    组合的方式完成授权
    继承的方式完成包装__attr__
    类的内置方法__attr__介绍
  • 原文地址:https://www.cnblogs.com/LzyRapx/p/9114391.html
Copyright © 2020-2023  润新知