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

转载于:https://www.cnblogs.com/luoyibujue/p/10508462.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值