zoukankan      html  css  js  c++  java
  • 有标号的二分图计数问题123

    • 因为OJ挂了, 所以三个代码实际上都是假代码, 应该不能过题.
    有标号的二分图计数1
    /*
    求n个点的二分图(可以不连通)的个数。n ≤10^5
    其中二分图进行了黑白染色,两个二分图不同:边不同 或 点的颜色不同
    
    然后答案就是枚举有几个点是黑的, 然后黑白点之间连边即可
    */
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<iostream>
    #include<queue>
    #include<cmath>
    #define ll long long
    #define M 100010
    #define mmp make_pair
    using namespace std;
    const int mod = 998244353;
    int read() {
    	int nm = 0, f = 1;
    	char c = getchar();
    	for(; !isdigit(c); c = getchar()) if(c == '-') f = -1;
    	for(; isdigit(c); c = getchar()) nm = nm * 10 + c - '0';
    	return nm * f;
    }
    int fac[M], inv[M], n;
    int poww(int a, int b) {
    	int ans = 1, tmp = a;
    	for(; b; b >>= 1, tmp = 1ll * tmp * tmp % mod) if(b & 1) ans = 1ll * ans * tmp % mod;
    	return ans;
    }
    int main() {
    	n = read();
    	fac[1] = inv[1] = 1;
    	for(int i = 1; i <= n; i++) fac[i] = 1ll * fac[i - 1] * i % mod;
    	inv[n] = poww(n, mod - 2);
    	for(int i = n - 1; i >= 1; i--) inv[i] = 1ll * inv[i + 1] * (i + 1) % mod;
    	int ans = 0;
    	for(int i = 0; i <= n; i++) {
    		ans = (ans + 1ll * fac[n] * inv[i] % mod * inv[n - i] % mod * poww(2, 1ll * i * (n - i) % (mod - 1)) % mod);
    	}
    	cout << ans << "
    ";
    	return 0;
    }
    
    
    有标号的二分图计数2
    /*
    接上题
    设F(x)为上题的生成函数 G(x)为本题的答案 H(x)为强制必须联通的方案
    那么G(x) = sum{i = 0} ^ {infty} frac{H(x) ^ i}{i!}
    考虑 F(x) = sum{i = 0} ^ {infty } frac{2 ^ i H(x) ^ i}{i!}
    显然 F(x) = G(x) ^ 2
    G(x) = F(x) ^ {1 / 2}
    下面考虑如何求F(x)
    
    首先组合数是显然的卷积形式, 但是2 ^ {k(n * k)} 需要转换成根号2的卷积形式
    
    */
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<iostream>
    #include<queue>
    #include<cmath>
    #define ll long long
    #define mmp make_pair
    using namespace std;
    int read() {
    	int nm = 0, f = 1;
    	char c = getchar();
    	for(; !isdigit(c); c = getchar()) if(c == '-') f = -1;
    	for(; isdigit(c); c = getchar()) nm = nm * 10 + c - '0';
    	return nm * f;
    }
    const int M = (1 << 20) + 5;
    const int  mod = 998244353;
    int add(int a, int b) {
    	a += b;
    	a -= a >= mod ? mod : 0;
    	a += a < 0  ? mod : 0;
    	return a;
    }
    
    int mul(int a, int b) {
    	return 1ll * a * b % mod;
    }
    
    int poww(int a, int b) {
    	int ans = 1, tmp = a;
    	for(; b; b >>= 1, tmp = mul(tmp, tmp)) if(b & 1) ans = mul(ans, tmp);
    	return ans;
    }
    
    namespace Poly {
    	const int g = 3;
    	int n;
    	int pw[M], rw[M];
    	void getw() {
    		for(int i = 1; i <= M; i <<= 1) {
    			pw[i] = poww(g, (mod - 1) / 2 / i);
    			rw[i] = poww(pw[i], mod - 2);
    		}
    	}
    
    	void init(int m) {
    		n = m;
    		while(n > (n & -n)) n += (n & -n);
    	}
    
    	void fft(int *x, int dft) {
    		for(int i = 0, j = 0; i < n; i++) {
    			if(i < j) swap(x[i], x[j]);
    			for(int l = n >> 1; (j ^= l) < l; l >>= 1);
    		}
    		for(int step = 1; step < n; step <<= 1) {
    			int wn = (dft == 1) ? pw[step] : rw[step];
    			for(int i = 0; i < n; i += step << 1) {
    				int wnk = 1;
    				for(int j = i; j < i + step; j++) {
    					int a = x[j], b = mul(wnk, x[j + step]);
    					x[j] = add(a, b);
    					x[j + step] = add(a, -b);
    					wnk = mul(wnk, wn);
    				}
    			}
    		}
    		if(dft == -1) {
    			int invn = poww(n, mod - 2);
    			for(int i = 0; i < n; i++) x[i] = mul(x[i], invn);
    		}
    	}
    
    	void pcpy(int *x, int a, int *y, int b) {
    		for(int i = 0; i < a; i++) {
    			x[i] = (i < b) ? y[i] : 0;
    		}
    	}
    
    	void pmul(int *x, int a, int *y, int b, int *z) {
    		static int tx[M + 5], ty[M + 5];
    
    		init(a + b - 1);
    		pcpy(tx, n, x, a);
    		pcpy(ty, n, y, b);
    		fft(tx, 1), fft(ty, 1);
    		for(int i = 0; i < n; i++) {
    			tx[i] = mul(tx[i], ty[i]);
    		}
    		fft(tx, -1);
    		for(int i = 0; i < a + b - 1; i++) {
    			z[i] = tx[i];
    		}
    	}
    
    	void pinv(int *x, int m, int *y) {
    		static int tx[M + 5], ty[M + 5];
    		if(m == 1) {
    			y[0] = poww(x[0], mod - 2);
    			return;
    		}
    		pinv(x, (m + 1) >> 1, y);
    
    		init(m << 1);
    		pcpy(tx, n, x, m);
    		pcpy(ty, n, y, (m + 1) >> 1);
    
    		fft(tx, 1), fft(ty, 1);
    		for(int i = 0; i < n; i++) {
    			tx[i] = 1ll * (2ll - 1ll * tx[i] * ty[i] % mod + mod) * ty[i] % mod;
    		}
    
    		fft(tx, -1);
    
    		for(int i = 0; i < m; i++) {
    			y[i] = tx[i];
    		}
    	}
    
    	void prev(int *x, int m, int *y) {
    		for(int i = 0; i < m; i++) y[i] = x[m - 1 - i];
    	}
    
    	void pdiv(int *x, int a, int *y, int b, int *z) {
    		static int tx[M + 5], ty[M + 5], tz[M + 5];
    
    		prev(x, a, tx);
    		prev(y, b, ty);
    
    		for(int i = b; i < a - b + 1; ++i) ty[i] = 0;
    
    		pinv(ty, a - b + 1, tz);
    		pmul(tx, a - b + 1, tz, a - b + 1, ty);
    		prev(ty, a - b + 1, z);
    	}
    
    	void pmod(int *x, int a, int *y, int b, int *z) {
    		static int tx[M + 5];
    
    		if(a < b) {
    			for(int i = 0; i < a; i++) {
    				z[i] = x[i];
    			}
    			return;
    		}
    
    		pdiv(x, a, y, b, tx);
    		pmul(tx, a - b + 1, y, b, tx);
    		for(int i = 0; i < b; i++) {
    			z[i] = (x[i] - tx[i] + mod) % mod;
    		}
    	}
    
    	void der(int *x, int m, int *y) {
    		for(int i = 1; i < m; i++) y[i - 1] = 1ll * i * x[i] % mod;
    		y[n - 1] = 0;
    	}
    
    	void inte(int *x, int m, int *y) {
    		for(int i = 1; i < m; i++) y[i] = 1ll * x[i - 1] * poww(i, mod - 2) % mod;
    		y[0] = 0;
    	}
    
    	void ln(int *x, int m, int *y) {
    		static int tx[M + 5], ty[M + 5], tz[M + 5];
    		der(x, m, tx);
    		pinv(x, m, ty);
    		pmul(tx, m, ty, m, tz);
    		inte(tz, m, y);
    	}
    // F0(x) (1 - ln(F0(x)) + A(x))
    
    	void exp(int *x, int m, int *y) {
    		static int ta[M + 5], tb[M + 5], tc[M + 5];
    		if(m == 1) {
    			y[0] = 1;
    			return;
    		}
    		exp(x, (m + 1) >> 1, y);
    		pcpy(ta, m, y, (m + 1) >> 1);
    		ln(ta, m, tb);
    		for(int i = 0; i < m; i++) {
    			tb[i] = add(x[i], -tb[i]);
    		}
    		tb[0] = add(tb[0], 1);
    		pcpy(ta, (m + 1) >> 1, y, (m + 1) >> 1);
    		pmul(ta, (m + 1) >> 1, tb, m, tc);
    		pcpy(y, m, tc, m);
    	}
    }
    
    
    int pool[M * 20], *cur = pool;
    
    struct poly {
    	int *a, l;
    	poly() {}
    	poly(int x) {
    		a = cur;
    		cur += (l = x);
    	}
    	poly(int *b, int x) {
    		a = cur, cur += (l = x);
    		memcpy(a, b, sizeof (int) * l);
    	}
    };
    
    poly operator * (const poly &a, const poly &b) {
    	poly c(a.l + b.l - 1);
    	Poly::pmul(a.a, a.l, b.a, b.l, c.a);
    	return c;
    }
    
    poly operator % (const poly &a, const poly &b) {
    	poly c(b.l - 1);
    	Poly::pmod(a.a, a.l, b.a, b.l, c.a);
    	return c;
    }
    
    poly operator / (const poly &a, const poly &b) {
    	poly c(b.l - 1);
    	Poly::pdiv(a.a, a.l, b.a, b.l, c.a);
    	return c;
    }
    
    poly ln(poly x) {
    	poly y(x.l);
    	Poly::ln(x.a, x.l, y.a);
    	return y;
    }
    
    poly exp_(poly x) {
    	poly y(x.l);
    	Poly::exp(x.a, x.l, y.a);
    	return y;
    }
    const int sqrt2 = 116195171;
    int fac[M], pw[M], n, a[M];
    int main() {
    	Poly::getw();
    	n = read() + 1;
    	fac[0] = a[0] = pw[0] = 1;
    	for(int i = 1; i < n; i++) {
    		fac[i] = 1ll * fac[i - 1] * i % mod, pw[i] = poww(sqrt2, 1ll * i * i % (mod - 1)) % mod;
    		a[i] = poww(mul(fac[i], pw[i]), mod - 2);
    	}
    	poly aa(n);
    	for(int i = 0; i < n; i++) aa.a[i] = a[i];
    	aa = aa * aa;
    	for(int i = 0; i < n; i++) aa.a[i] = mul(aa.a[i], pw[i]);
    	poly c = ln(aa);
    	int inv = poww(2, mod - 2);
    	for(int i = 0; i < n; i++) c.a[i] = mul(c.a[i], inv);
    	poly d = exp_(c);
    	cout << 1ll * d.a[n - 1] * fac[n - 1] % mod;
    	return 0;
    }
    
    
    有标号的二分图计数3
    /*
    接上题
    根据上面那个题目推的式子
    F(x) = e^{2H(x)}
    那么显然H(x)等于frac{ln(F(x))}{2}了
    */
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<iostream>
    #include<queue>
    #include<cmath>
    #define ll long long
    #define mmp make_pair
    using namespace std;
    int read() {
    	int nm = 0, f = 1;
    	char c = getchar();
    	for(; !isdigit(c); c = getchar()) if(c == '-') f = -1;
    	for(; isdigit(c); c = getchar()) nm = nm * 10 + c - '0';
    	return nm * f;
    }
    const int M = (1 << 20) + 5;
    const int  mod = 998244353;
    int add(int a, int b) {
    	a += b;
    	a -= a >= mod ? mod : 0;
    	a += a < 0  ? mod : 0;
    	return a;
    }
    
    int mul(int a, int b) {
    	return 1ll * a * b % mod;
    }
    
    int poww(int a, int b) {
    	int ans = 1, tmp = a;
    	for(; b; b >>= 1, tmp = mul(tmp, tmp)) if(b & 1) ans = mul(ans, tmp);
    	return ans;
    }
    
    namespace Poly {
    	const int g = 3;
    	int n;
    	int pw[M], rw[M];
    	void getw() {
    		for(int i = 1; i <= M; i <<= 1) {
    			pw[i] = poww(g, (mod - 1) / 2 / i);
    			rw[i] = poww(pw[i], mod - 2);
    		}
    	}
    
    	void init(int m) {
    		n = m;
    		while(n > (n & -n)) n += (n & -n);
    	}
    
    	void fft(int *x, int dft) {
    		for(int i = 0, j = 0; i < n; i++) {
    			if(i < j) swap(x[i], x[j]);
    			for(int l = n >> 1; (j ^= l) < l; l >>= 1);
    		}
    		for(int step = 1; step < n; step <<= 1) {
    			int wn = (dft == 1) ? pw[step] : rw[step];
    			for(int i = 0; i < n; i += step << 1) {
    				int wnk = 1;
    				for(int j = i; j < i + step; j++) {
    					int a = x[j], b = mul(wnk, x[j + step]);
    					x[j] = add(a, b);
    					x[j + step] = add(a, -b);
    					wnk = mul(wnk, wn);
    				}
    			}
    		}
    		if(dft == -1) {
    			int invn = poww(n, mod - 2);
    			for(int i = 0; i < n; i++) x[i] = mul(x[i], invn);
    		}
    	}
    
    	void pcpy(int *x, int a, int *y, int b) {
    		for(int i = 0; i < a; i++) {
    			x[i] = (i < b) ? y[i] : 0;
    		}
    	}
    
    	void pmul(int *x, int a, int *y, int b, int *z) {
    		static int tx[M + 5], ty[M + 5];
    
    		init(a + b - 1);
    		pcpy(tx, n, x, a);
    		pcpy(ty, n, y, b);
    		fft(tx, 1), fft(ty, 1);
    		for(int i = 0; i < n; i++) {
    			tx[i] = mul(tx[i], ty[i]);
    		}
    		fft(tx, -1);
    		for(int i = 0; i < a + b - 1; i++) {
    			z[i] = tx[i];
    		}
    	}
    
    	void pinv(int *x, int m, int *y) {
    		static int tx[M + 5], ty[M + 5];
    		if(m == 1) {
    			y[0] = poww(x[0], mod - 2);
    			return;
    		}
    		pinv(x, (m + 1) >> 1, y);
    
    		init(m << 1);
    		pcpy(tx, n, x, m);
    		pcpy(ty, n, y, (m + 1) >> 1);
    
    		fft(tx, 1), fft(ty, 1);
    		for(int i = 0; i < n; i++) {
    			tx[i] = 1ll * (2ll - 1ll * tx[i] * ty[i] % mod + mod) * ty[i] % mod;
    		}
    
    		fft(tx, -1);
    
    		for(int i = 0; i < m; i++) {
    			y[i] = tx[i];
    		}
    	}
    
    	void prev(int *x, int m, int *y) {
    		for(int i = 0; i < m; i++) y[i] = x[m - 1 - i];
    	}
    
    	void pdiv(int *x, int a, int *y, int b, int *z) {
    		static int tx[M + 5], ty[M + 5], tz[M + 5];
    
    		prev(x, a, tx);
    		prev(y, b, ty);
    
    		for(int i = b; i < a - b + 1; ++i) ty[i] = 0;
    
    		pinv(ty, a - b + 1, tz);
    		pmul(tx, a - b + 1, tz, a - b + 1, ty);
    		prev(ty, a - b + 1, z);
    	}
    
    	void pmod(int *x, int a, int *y, int b, int *z) {
    		static int tx[M + 5];
    
    		if(a < b) {
    			for(int i = 0; i < a; i++) {
    				z[i] = x[i];
    			}
    			return;
    		}
    
    		pdiv(x, a, y, b, tx);
    		pmul(tx, a - b + 1, y, b, tx);
    		for(int i = 0; i < b; i++) {
    			z[i] = (x[i] - tx[i] + mod) % mod;
    		}
    	}
    
    	void der(int *x, int m, int *y) {
    		for(int i = 1; i < m; i++) y[i - 1] = 1ll * i * x[i] % mod;
    		y[n - 1] = 0;
    	}
    
    	void inte(int *x, int m, int *y) {
    		for(int i = 1; i < m; i++) y[i] = 1ll * x[i - 1] * poww(i, mod - 2) % mod;
    		y[0] = 0;
    	}
    
    	void ln(int *x, int m, int *y) {
    		static int tx[M + 5], ty[M + 5], tz[M + 5];
    		der(x, m, tx);
    		pinv(x, m, ty);
    		pmul(tx, m, ty, m, tz);
    		inte(tz, m, y);
    	}
    // F0(x) (1 - ln(F0(x)) + A(x))
    
    	void exp(int *x, int m, int *y) {
    		static int ta[M + 5], tb[M + 5], tc[M + 5];
    		if(m == 1) {
    			y[0] = 1;
    			return;
    		}
    		exp(x, (m + 1) >> 1, y);
    		pcpy(ta, m, y, (m + 1) >> 1);
    		ln(ta, m, tb);
    		for(int i = 0; i < m; i++) {
    			tb[i] = add(x[i], -tb[i]);
    		}
    		tb[0] = add(tb[0], 1);
    		pcpy(ta, (m + 1) >> 1, y, (m + 1) >> 1);
    		pmul(ta, (m + 1) >> 1, tb, m, tc);
    		pcpy(y, m, tc, m);
    	}
    }
    
    
    int pool[M * 20], *cur = pool;
    
    struct poly {
    	int *a, l;
    	poly() {}
    	poly(int x) {
    		a = cur;
    		cur += (l = x);
    	}
    	poly(int *b, int x) {
    		a = cur, cur += (l = x);
    		memcpy(a, b, sizeof (int) * l);
    	}
    };
    
    poly operator * (const poly &a, const poly &b) {
    	poly c(a.l + b.l - 1);
    	Poly::pmul(a.a, a.l, b.a, b.l, c.a);
    	return c;
    }
    
    poly operator % (const poly &a, const poly &b) {
    	poly c(b.l - 1);
    	Poly::pmod(a.a, a.l, b.a, b.l, c.a);
    	return c;
    }
    
    poly operator / (const poly &a, const poly &b) {
    	poly c(b.l - 1);
    	Poly::pdiv(a.a, a.l, b.a, b.l, c.a);
    	return c;
    }
    
    poly ln(poly x) {
    	poly y(x.l);
    	Poly::ln(x.a, x.l, y.a);
    	return y;
    }
    
    poly exp_(poly x) {
    	poly y(x.l);
    	Poly::exp(x.a, x.l, y.a);
    	return y;
    }
    const int sqrt2 = 116195171;
    int fac[M], pw[M], n, a[M];
    int main() {
    	Poly::getw();
    	n = read() + 1;
    	fac[0] = a[0] = pw[0] = 1;
    	for(int i = 1; i < n; i++) {
    		fac[i] = 1ll * fac[i - 1] * i % mod, pw[i] = poww(sqrt2, 1ll * i * i % (mod - 1)) % mod;
    		a[i] = poww(mul(fac[i], pw[i]), mod - 2);
    	}
    	poly aa(n);
    	aa = aa * aa;
    	for(int i = 0; i < n; i++) aa.a[i] = mul(aa.a[i], pw[i]);
    	poly c = ln(aa);
    	cout << mul(mul(c.a[n - 1], fac[n - 1]), poww(2, mod - 2)) << "
    ";
    	return 0;
    }
    
    
  • 相关阅读:
    2018.09.08什么是ajax
    2018.09.03怎样让网页自适应所有屏幕宽度
    2018.08.25字符串和二维数组之间的转换
    2018.08.20MySQL常用命令总结(二)
    2018.08.15解决MySQL1290问题
    2018.08.13MySQL常用命令总结(一)
    2018.08.11MySQL无法启动错误码1067的解决方法
    2018.08.10 css中position定位问题
    2018.08.10jQuery导航栏置顶
    2018.08.07css实现图片放大
  • 原文地址:https://www.cnblogs.com/luoyibujue/p/10508462.html
Copyright © 2011-2022 走看看