zoukankan      html  css  js  c++  java
  • bzoj 5093 图的价值

    定义一个图的价值为每个点度数 $k$ 次方之和,求所有 $n$ 个点的简单图价值之和,膜 998244353

    $n leq 10^9, k leq 2 imes 10^5$

    sol:

    发现每个点是本质相同的,我们考虑枚举一个点的贡献,最后乘以 $n$

    我们可以枚举它连出去多少条边,这个点连出去边有多少种方案,剩下图有多少种方案

    显然,一个点连出去 $i$ 条边有 $inom{n-1}{i}$ 种方案,而每种方案的贡献为 $i^k$

    考虑剩下图的方案,发现剩下图长什么样跟这个点没关系,那就是 $2^{frac{(n - 1) imes (n - 2)}{2}}$ 种方案

    整体就是 $n imes 2^{frac{(n - 1) imes (n - 2)}{2}} imes sumlimits_{i=0}^{n-1} inom{n-1}{i}  imes i^k$

    考虑把 $i^k$ 用斯特林数展开,变成 $sumlimits_{i=0}^k inom{k}{i} imes S2(k,i) imes i!$

    先不算 $n imes 2^{frac{(n - 1) imes (n - 2)}{2}}$,剩下的式子是 $sumlimits_{i=0}^n inom{n-1}{i} imes sumlimits_{j=0}^k inom{i}{j} imes S2(k,j) imes j!$

    把所有组合数拆开:$(n-1)! imes sumlimits_{i=0}^n frac{1}{(n-i-1)!} imes sumlimits_{j=0}^k S2(k,j) imes frac{1}{(i-j)!}$

    交换求和顺序 $(n-1)! imes sumlimits_{j=0}^k S2(k,j)  imes sumlimits_{i=0}^n  frac{1}{(i-j)! imes (n-i-1)!}$

    提取一个组合数 $(n-1)! imes sumlimits_{j=0}^k S2(k,j)  imes sumlimits_{i=0}^n inom{n-j-1}{n-i-1} imes frac{1}{(n-j-1)!}$

    用一下杨辉三角一排的和 $sumlimits_{j=0}^k S2(k,j)  imes 2^{n-j-1} imes frac{(n-1)!}{(n-j-1)!}$

    然后发现要算的就是一行第二类斯特林数,考虑斯特林数的容斥形式

    $S2(k,j) = sumlimits_{i=0}^j frac{(-1)^i}{i!} imes frac{(j-i)^k}{(j-i)!}$

    然后直接求就完事了

    #include <bits/stdc++.h>
    #define LL long long
    #define rep(i, s, t) for (register int i = (s), i##end = (t); i <= i##end; ++i)
    #define dwn(i, s, t) for (register int i = (s), i##end = (t); i >= i##end; --i)
    using namespace std;
    inline int read() {
        int x = 0,f = 1; char ch = getchar();
        for(; !isdigit(ch); ch = getchar())if(ch == '-') f = -f;
        for(; isdigit(ch); ch = getchar())x = 10 * x + ch - '0';
        return x * f;
    }
    const int maxn = 1000010, mod = 998244353;
    inline int inc(int x, int y) {x += y; if(x >= mod) x -= mod; return x;}
    inline int dec(int x, int y) {x -= y; if(x < 0) x += mod; return x;}
    inline int mul(int x, int y) {return 1LL * x * y % mod;}
    int n, k;
    int A[maxn], B[maxn], Sk[maxn];
    int lg[maxn], r[maxn], wn[(1 << 19) + 10], iwn[(1 << 19) + 10], fac[maxn], ifac[maxn], inv[maxn];
    inline int ksm(int x, LL t, int res = 1) {
        for(; t; x = mul(x, x), t >>= 1)
            if(t & 1) res = mul(res, x); return res;
    }
    void init_fac() {
        lg[0] = -1; rep(i, 1, maxn - 10) lg[i] = lg[i >> 1] + 1;
        fac[0] = ifac[0] = 1; rep(i, 1, maxn - 10) fac[i] = mul(fac[i - 1], i);
        ifac[maxn - 10] = ksm(fac[maxn - 10], mod - 2); dwn(i, maxn - 11, 1) ifac[i] = mul(ifac[i + 1], i + 1);
        inv[0] = inv[1] = 1; rep(i, 2, maxn - 10) inv[i] = mul((mod - mod / i), inv[mod % i]);
        int lim = (1 << 19); wn[0] = iwn[0] = 1;
        rep(i, 1, lim-1) wn[i] = ksm(3, (mod - 1) / (i << 1)), iwn[i] = ksm(332748118, (mod - 1) / (i << 1));
    }
    void fft(int *a, int n, int f) {
        rep(i, 0, n-1) r[i] = (r[i >> 1] >> 1) | ((i & 1) << (lg[n] - 1));
        rep(i, 0, n-1) if(i < r[i]) swap(a[i], a[r[i]]);
        for(register int i = 1; i < n; i <<= 1) {
            int now = (~f) ? wn[i] : iwn[i];
            for(register int j = 0; j < n; j += (i << 1)) {
                int w = 1;
                for(register int k = 0; k < i; ++k, w = mul(w, now)) {
                    int x = a[j + k], y = mul(w, a[j + k + i]);
                    a[j + k] = inc(x, y); a[j + k + i] = dec(x, y);
                }
            }
        }
        if(f == -1) rep(i, 0, n-1) a[i] = mul(a[i], inv[n]);
    }
    int C(int x, int y) {
        if(y > x) return 0; if(y == 0) return 1;
        return mul(mul(fac[x], ifac[y]), ifac[x - y]);
    }
    int main() {
        n = read(), k = read(); init_fac();
        int len = 1; for(; len <= (k<<1); len <<= 1);
        rep(i, 0, k) A[i] = mul(((i & 1) ? (mod-1) : 1), ifac[i]);
        rep(i, 0, k) B[i] = mul(ksm(i, k), ifac[i]);
        fft(A, len, 1); fft(B, len, 1);
        rep(i, 0, len - 1) Sk[i] = mul(A[i], B[i]);
        fft(Sk, len, -1); int ans = 0;
        //rep(i, 1, k) cout << Sk[i] << " ";
        //cout << endl;
        LL cni = 1, cur = n - 1;
        rep(i, 0, min(n - 1, k)) {
            ans = inc(ans, mul(mul(Sk[i], cni), ksm(2, n - i - 1)));
            cni = mul(cni, cur); cur--;
        }
        ans = mul(ans, mul(n, ksm(2, 1LL * (n - 2) * (n - 1) / 2 % (mod - 1))));
        cout << ans << endl;
    }
    View Code
  • 相关阅读:
    目前主要的测试用例设计方法是什么?
    软件的安全性应从哪几个方面去测试?
    软件产品质量特性是什么?
    在您以往的工作中,一条软件缺陷(或者叫Bug)记录都包含了哪些内容?如何提交高质量的软件缺陷(Bug)记录?
    简述什么是静态测试、动态测试、黑盒测试、白盒测试、α测试 β测试
    详细的描述一个测试活动完整的过程
    在搜索引擎中输入汉字就可以解析到对应的域名,请问如何用LoadRunner进行测试。
    String是最基本的数据类型吗?
    1、面向对象的特征有哪些方面
    说出Servlet的生命周期,并说出Servlet和CGI的区别。
  • 原文地址:https://www.cnblogs.com/Kong-Ruo/p/10603203.html
Copyright © 2011-2022 走看看