• 题解 P4233 【射命丸文的笔记】 && 考试T3


    • 考虑每一条哈密顿回路在所有竞赛图中的出现次数。
    • 发现如果确定一个环, 其他的边乱选就可以保证出现哈密顿回路。所以对于一条哈密顿回路, 出现次数为(2^{C_n^2-n}), 减去的(n)为那(n)条边。哈密顿回路是(1-n)的一个排列首尾拼在一起, 共有(n!/n)种。于是总贡献可以直接得出。
    • 总贡献算好了, 问题转化为求有多少个存在哈密顿回路的竞赛图。
    • 显然, 存在哈密顿回路的竞赛图一定强连通, 强连通的竞赛图一定有哈密顿回路。
    • 所以问题就是求有多少个强连通的(n)个点的竞赛图。
    • (n)个点的强连通的竞赛图个数为(f_n)
    • 考虑用所有图减去不是强连通的竞赛图, 可以得到:

      [f_n =2^{C_n^2} - sum_{i=1}^{n - 1}f_i imes C_n^i imes 2^{C_{n - i}^2} ]

    • 这个式子的意思是枚举一个其他点无法到达的强连通图,也就是缩点之后拓扑序最小的强连通图,由于是任意的, 所以乘以组合数, 然后剩下的点数为(n - i)的图乱选。之所以可以这样是因为每个图一定会有一个最小的强连通图, 而且由于对于每个图我们只统计最小的, 所以做到不重不漏。
    • 考虑如何计算(f_i)
    • (g_i=2^{C_i^2}), 有:

    [f_n=g_n-sum_{i=1}^{n-1}f_i imes C_n^i imes g_{n-i} ]

    [g_n=sum_{i=1}^nf_i imes C_n^i imes g_{n-i} ]

    [frac{g_n}{n!}=sum_{i=1}^nfrac{f_i}{i!} imes frac{g_{n-i}}{(n-i)!} ]

    • (G_n=frac{g_n}{n!}), (F_n=frac{f_n}{n!})
    • 所以有:

      [G_n = sum_{i=1}^nF_iG_{n-i} ]

    • (A=sum_{i = 0}^{inf}F_ix^i), (B=sum_{i=0}^{inf}G_ix^i), 然后有:

    [A * B=sum_{i=0}^{inf}x^isum_{j+k=i}F_j imes G_k = B - G_0 ]

    • 这里(G_0 = 0)
    • 移项,多项式求逆就好了。
    #include <cmath>
    #include <cstdio>
    #include <vector>
    #include <cstring>
    #include <algorithm>
    #include <iostream>
    
    using namespace std;
    
    #define R register
    const int N = 4e5 + 10;
    const int P = 998244353;
    const int G = 3;
    
    inline int read() {
    	int x = 0, f = 1; char a = getchar();
    	for(; a > '9' || a < '0'; a = getchar()) if(a == '-') f = -1;
    	for(; a >= '0' && a <= '9'; a = getchar()) x = x * 10 + a - '0';
    	return x * f;
    }
    template <typename T>
    inline int qpow(int x, T k) {
    	int res = 1;
    	while(k) {
    		if(k & 1) res = 1LL * res * x % P;
    		x = 1LL * x * x % P; k >>= 1;
    	} return res;
    } 
    
    struct Poly {
    	int lim, rev[N];
    	inline void init(int Lim) {
    		lim = Lim;
    		for(R int i = 0; i < lim; i ++)
    			rev[i] = (rev[i >> 1] >> 1) | ((i & 1) ? lim >> 1 : 0);
    	}
    	inline void NTT(int *A, int type = 1) {
    		for(R int i = 0; i < lim; i ++) if(i > rev[i]) swap(A[i], A[rev[i]]);
    		for(R int dep = 1; dep < lim; dep <<= 1) {
    			int Wn = qpow(type == 1 ? G : qpow(G, P - 2), (P - 1) / (dep << 1));
    			for(R int j = 0, len = dep << 1; j < lim; j += len) {
    				int w = 1;
    				for(R int k = 0; k < dep; k ++, w = 1LL * w * Wn % P) {
    					int x = A[j + k], y = 1LL * w * A[j + k + dep] % P;
    					A[j + k] = (x + y) % P;
    					A[j + k + dep] = (x - y + P) % P;
    				}
    			}
    		}
    		if(type == -1) {
    			int inv = qpow(lim, P - 2);
    			for(R int i = 0; i < lim; i ++) A[i] = 1LL * A[i] * inv % P;
    		}
    	}
    	int C[N];
    	inline void getinv(int dep, int *F, int *G) {
    		if(dep == 1) {
    			G[0] = qpow(F[0], P - 2); return ;
    		}
    		getinv((dep + 1) >> 1, F, G);
    		int lim = 1;
    		while(lim < (dep << 1)) lim <<= 1; init(lim);
    		for(R int i = 0; i < dep; i ++) C[i] = F[i]; 
    		for(R int i = dep + 1; i < lim; i ++) C[i] = 0;
    		NTT(C); NTT(G);
    		for(R int i = 0; i < lim; i ++) 
    			G[i] = 1LL * (2 - 1LL * C[i] * G[i] % P + P) % P * G[i] % P;
    		NTT(G, -1);
    		for(R int i = dep; i < lim; i ++) G[i] = 0;
    	}
    }T;
    int n;
    int f[N], g[N], F[N];
    int fac[N], ifac[N];
    int main() {
    	freopen("hamilton.in", "r", stdin);
    	freopen("hamilton.out", "w", stdout);
    	n = read(); fac[0] = 1;
    	if(n >= 1) cout << 1 << endl;
    	if(n >= 2) cout << -1 << endl;
    	for(R int i = 1; i <= n; i ++) fac[i] = 1LL * fac[i - 1] * i % P;
    	ifac[n] = qpow(fac[n], P - 2);
    	for(R int i = n - 1; i >= 0; i --) ifac[i] = 1LL * ifac[i + 1] * (i + 1) % P;
    	for(R int i = 0; i <= n; i ++) g[i] = 1LL * qpow(2, 1LL * i * (i - 1) / 2) * ifac[i] % P;
    	T.getinv(n + 1, g, F);
    	for(R int i = 0; i <= n; i ++) F[i] = (P - F[i]) % P;
    	for(R int i = 0; i <= n; i ++) f[i] = 1LL * F[i] * fac[i] % P;
    	for(R int i = 0; i <= n; i ++) g[i] = 1LL * g[i] * fac[i] % P;
    	for(R int i = 3; i <= n; i ++) 
    printf("%lld
    ", 1LL * fac[i] * qpow(i, P - 2) % P * qpow(2, 1LL * i * (i - 1) / 2 - i) % P * qpow(f[i], P - 2) % P) ;
    	return 0;
    }
    
    
  • 相关阅读:
    导包路径
    django导入环境变量 Please specify Django project root directory
    替换django的user模型,mysql迁移表报错 django.db.migrations.exceptions.InconsistentMigrationHistory: Migration admin.0001_initial is applied before its dependen cy user.0001_initial on database 'default'.
    解决Chrome调试(debugger)
    check the manual that corresponds to your MySQL server version for the right syntax to use near 'order) values ('徐小波','XuXiaoB','男','1',' at line 1")
    MySQL命令(其三)
    MySQL操作命令(其二)
    MySQL命令(其一)
    [POJ2559]Largest Rectangle in a Histogram (栈)
    [HDU4864]Task (贪心)
  • 原文地址:https://www.cnblogs.com/clover4/p/13506016.html
Copyright © 2020-2023  润新知