首页 > 其他分享 >CatOJ C0493C 计数 分讨

CatOJ C0493C 计数 分讨

时间:2024-03-02 16:57:44浏览次数:25  
标签:cnt pw int sum CatOJ 分讨 ans C0493C mod

对于 \(\sum |E'|\),直接计算是简单的。

对于 \(\sum |E'|^2\),拆下贡献,可以拆成 \(\sum\sum_{i,j\in E'}1\),设 \(U\) 为 \(i\) 和 \(j\) 两条边连接的点集,转化一下式子即为 \(\sum_i\sum_j2^{n-|U|}\)。对于 \(\sum |E'|^3\) 同理,\(U\) 为 \(i,j,k\) 三条边连接的点集,原式即为 \(\sum_i\sum_j\sum_k2^{n-|U|}\)。

于是我们可以对 \(|U|\) 分讨计数:(这里贺一下官方题解)

容斥一下即可,感觉直接给代码比干讲更好理解些
#include <bits/stdc++.h>
using namespace std;
#define rep(i, x, y) for (int i = (x); i <= (y); i++)
#define per(i, x, y) for (int i = (x); i >= (y); i--) 
#define int long long
using ll = long long; using ull = unsigned long long;
inline int read() {
    char ch = getchar(); int s = 0, f = 1;
    while (!isdigit(ch)) {if (ch == '-') f = -1; ch = getchar();}
    while (isdigit(ch)) s = (s << 1) + (s << 3) + (ch ^ 48), ch = getchar();
    return s * f;
}
constexpr int N = 1e5 + 5, mod = 1e9 + 7;
int n, m, k, pw[N], fac[N], ifac[N], inv[N];
inline int C(int x, int y) {
    if (x < y || x < 0 || y < 0) return 0;
    return fac[x] * ifac[x - y] % mod * ifac[y] % mod;
}
namespace sub1 {
    int f[N], g[N];
    inline int sol() {
        pw[0] = 1; rep (i, 1, N - 5) pw[i] = pw[i - 1] * 2 % mod;
        rep (i, 1, m) {
            int u = read(), v = read();
            if (u > v) swap(u, v);
            (g[v] += pw[v - 2]) %= mod;
        } 
        rep (i, 2, n) {
            f[i] = (f[i - 1] * 2 + g[i]) % mod;
        } cout << f[n]; return 0;
    }
}
namespace sub2 {
    int d[N];
    inline int sol() {
        // |U| = 2
        int ans = m * pw[n - 2], cnt = C(m, 2);
        
        while (m--) {
            int u = read(), v = read();
            d[u]++, d[v]++;
        }
        // |U| = 3
        rep (i, 1, n) {
            (ans += C(d[i], 2) * pw[n - 3] * 2) %= mod;
            (cnt -= C(d[i], 2)) %= mod;
        } 
        // |U| = 4
        (ans += cnt * pw[n - 4] * 2) %= mod;
        
        cout << (ans + mod) % mod;
        return 0;
    }
}
namespace sub3 {
    int d[N], vis[N]; array<int, 2> E[N];
    vector<int> e[N]; 
    inline int sol1() {
        int res = 0;
        rep (i, 1, m) {
            int u = E[i][0], v = E[i][1];
            if (d[u] > d[v]) swap(u, v);
            else if (d[u] == d[v] && u > v) swap(u, v);
            e[u].push_back(v);
        }
        rep (u, 1, n) {
            for (auto v : e[u]) vis[v] = u;
            for (auto v : e[u]) for (auto w : e[v]) 
                if (vis[w] == u) res++;
        } return res;
    }
    inline int sol() {
        int ans = 0, cnt = m * m * m, c2 = C(m, 2), cc = 0, c1 = 0;
        rep (i, 1, m) {
            int u = read(), v = read();
            d[u]++, d[v]++;
            E[i] = {u, v};
        } 
        // |U| = 2
        (cnt -= m) %= mod, (ans += m * pw[n - 2]) %= mod;
        // |U| = 3 
        int x = sol1();
        (ans += x * pw[n - 3] * 6) %= mod;
        (cnt -= x * 6) %= mod;
        rep (i, 1, n) {
            (ans += C(d[i], 2) * pw[n - 3] * 6) %= mod;
            (cnt -= C(d[i], 2) * 6) %= mod;
            (c2 -= C(d[i], 2)) %= mod;
            (cc += C(d[i], 2)) %= mod;
        } 
        // |U| = 4
        (ans += c2 * pw[n - 4] * 6) %= mod, (cnt -= c2 * 6) %= mod;
        int s = -x * 3;
        rep (i, 1, m) {
            int u = E[i][0], v = E[i][1];
            (s += (d[u] - 1) * (d[v] - 1)) %= mod; 
        }
        (ans += s * pw[n - 4] * 6) %= mod, (cnt -= s * 6) %= mod;
        rep (i, 1, n) {
            (ans += C(d[i], 3) * pw[n - 4] * 6) %= mod;
            (cnt -= C(d[i], 3) * 6) %= mod;
            (c1 += C(d[i], 3)) %= mod;
        } 
        // |U| = 5
        int y = (cc * (m - 2) - c1 * 3 - s * 2 - x * 3) % mod;
        (ans += y * pw[n - 5] * 6) %= mod, (cnt -= y * 6) %= mod;
        // |U| = 6
        (ans += cnt * pw[n - 6]) %= mod;

        cout << (ans + mod) % mod; return 0;
    }
}
signed main() {
    ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    n = read(), m = read(), k = read();
    pw[0] = fac[0] = ifac[0] = fac[1] = ifac[1] = inv[1] = 1; pw[1] = 2;
    rep (i, 2, N - 5) {
        pw[i] = pw[i - 1] * 2 % mod;
        fac[i] = fac[i - 1] * i % mod;
        inv[i] = (mod - mod / i) * inv[mod % i] % mod;
        ifac[i] = ifac[i - 1] * inv[i] % mod;
    }
    if (k == 1) return sub1::sol();
    if (k == 2) return sub2::sol();
    if (k == 3) return sub3::sol();
    return 0;
}

标签:cnt,pw,int,sum,CatOJ,分讨,ans,C0493C,mod
From: https://www.cnblogs.com/kxwenorz/p/18048829

相关文章

  • 【题解】CatOJ C0458C 滑动窗口定期重构
    标题trick的名字我也不知道是什么,就这样吧。link。首先有显然的dp式子:\(f(i)=\min\{f(j)\times\max\{a_{j+1},\dots,a_i\}\}\)。考虑怎么去优化它。有显然的\(\mathcalO(n\logn)\):考虑线段树优化dp。用增的单调栈维护\(a\),若每次弹出顶部一个下标\(p\),则\([p+1,i......
  • #12 讨厌分讨
    MirianyandMatchstick题面令\(f_{i,0/1,j}\)表示第\(i\)个数选A或B能否产生\(j\)的价值,枚举转移可以做到\(O(n^2)\)。可以发现\(1\)答案为\(1\)的\(j\)在分奇偶后都是一段区间,两个并起来会是一个中间最多一个空缺,证明可以看CF1852D题解,可以维护每个\(f_{i......
  • 关于转移中需要根据期望相对大小进行分讨的期望 dp
    转移式形如\(\displaystylef_i=\sum_{f_i>f_j}g(i,j)f_j+\sum_{f_i<f_j}h(i,j)\boldsymbol{f_i}\)。考虑初始化所有\(f_i\)为正无穷,化一下式子后发现......