有标号的二分图计数问题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;
}

原文地址:https://www.cnblogs.com/luoyibujue/p/10508462.html