- 因为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 << "\n";
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)) << "\n";
return 0;
}