• [校内训练]无向图(第二类斯特林数)


    problem

    • 定义一个点的权值为它的度数的 \(m\) 次方,规定 \(0^0=1\)
    • 对于一张无向图,它的权值是所有点的权值和。
    • 求所有 \(n\) 个点的无向图(共有 \(2^{C_n^2}\) 种)的权值之和,对 \(998244353\) 取模。
    • \(1≤n≤10^9,0≤m≤5*10^5\)

    Solution

    • 分别考虑每个点对答案的贡献:固定一个点 \(u\),枚举 \(u\) 的度数 \(i\),对答案的贡献为 \(i^m\)。而满足 \(u\) 度数为 \(i\) 的图中,另外 \(n-1\) 个点要选出 \(i\) 个点跟 \(u\) 连边(方案数:\(C_{n-1}^i\))。然后另外 \(n-1\) 个点两两之间可以随意连边(方案数:\(2^{C_{n-1}^2}\))。而 \(u\) 可以是 \(1\) ~ \(n\) 的任意一个点,所以有:

    \[ans=n*2^{C_{n-1}^2}*\sum_{i=0}^{n-1}i^m*C_{n-1}^i \]

    • 显然我们只要求:

    \[sum=\sum_{i=0}^{n-1}i^m*C_{n-1}^i \]

    • 众所周知:

    \[i^m=\sum_{j=0}^{m}S(m,j)*C_i^j*j! \]

    • 那么有:

    \[sum=\sum_{j=0}^{m}S(m,j)*j!*\sum_{i=0}^{n-1}C_i^j*C_{n-1}^i \]

    • 考虑 \(C_i^j*C_{n-1}^i\) 的组合意义:\(n-1\) 个带编号的球里面选出 \(i\) 个涂成蓝色,再在这 \(i\) 个里面选出 \(j\) 个涂成红色。这等价于:\(n-1\) 个带编号的球里面选出 \(j\) 个涂成红色,再在剩下的 \(n-j-1\) 个里面选出 \(i-j\) 个涂成蓝色。
    • 那么有:

    \[sum=\sum_{j=0}^{m}S(m,j)*j!*C_{n-1}^j*\sum_{i=0}^{n-1}C_{n-j-1}^{i-j} \]

    • 即:

    \[sum=\sum_{j=0}^{m}S(m,j)*j!*C_{n-1}^j*2^{n-j-1} \]

    • 众所周知:

    \[S(m,j)=\frac{1}{j!}\sum_{i=0}^{j}(-1)^i*(j-i)^n*C_j^i \]

    • 那么我们可以用 \(NTT\) 求出每个 \(S(m,j)\),时间复杂度 \(O(m \log m)\)

    Code

    #include <bits/stdc++.h>
    
    using namespace std;
    
    #define ll long long
    
    template <class t>
    inline void read(t & res)
    {
    	char ch;
    	while (ch = getchar(), !isdigit(ch));
    	res = ch ^ 48;
    	while (ch = getchar(), isdigit(ch))
    	res = res * 10 + (ch ^ 48);
    }
    
    const int mod = 998244353, e = 2e6 + 5;
    int n, m, lim, rev[e], g[e], h[e], f[e], fac[e], inv[e], ans;
    
    inline int ksm(int x, ll y)
    {
    	int res = 1;
    	while (y)
    	{
    		if (y & 1) res = (ll)res * x % mod;
    		y >>= 1;
    		x = (ll)x * x % mod;
    	}
    	return res;
    }
    
    inline void upt(int &x, int y)
    {
    	x = y;
    	if (x >= mod) x -= mod;
    }
    
    inline void fft(int n, int *a, int op)
    {
    	int i, j, k, r = (op == 1 ? 3 : (mod + 1) / 3);
    	for (i = 0; i < n; i++)
    	if (i < rev[i]) swap(a[i], a[rev[i]]);
    	for (k = 1; k < n; k <<= 1)
    	{
    		int w0 = ksm(r, (mod - 1) / (k << 1));
    		for (i = 0; i < n; i += (k << 1))
    		{
    			int w = 1;
    			for (j = 0; j < k; j++)
    			{
    				int b = a[i + j], c = (ll)w * a[i + j + k] % mod;
    				upt(a[i + j], b + c);
    				upt(a[i + j + k], b + mod - c);
    				w = (ll)w * w0 % mod;
    			}
    		}
    	}
    }
    
    int main()
    {
    	freopen("graph.in", "r", stdin);
    	freopen("graph.out", "w", stdout);
    	cin >> n >> m;
    	lim = 1;
    	int i, k = 0;
    	while (lim < m * 2 + 5)
    	{
    		lim <<= 1;
    		k++;
    	}
    	fac[0] = 1;
    	for (i = 1; i <= m; i++) fac[i] = (ll)fac[i - 1] * i % mod;
    	inv[m] = ksm(fac[m], mod - 2);
    	for (i = m - 1; i >= 0; i--) inv[i] = (ll)inv[i + 1] * (i + 1) % mod;
    	for (i = 0; i < lim; i++) rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << k - 1);
    	for (i = 0; i <= m; i++)
    	{
    		if (i & 1) g[i] = mod - 1;
    		else g[i] = 1;
    		g[i] = (ll)g[i] * inv[i] % mod;
    		h[i] = (ll)inv[i] * ksm(i, m) % mod;
    	}
    	fft(lim, g, 1);
    	fft(lim, h, 1);
    	for (i = 0; i < lim; i++) f[i] = (ll)g[i] * h[i] % mod;
    	fft(lim, f, -1);
    	int tot = ksm(lim, mod - 2);
    	for (i = 0; i < lim; i++) f[i] = (ll)f[i] * tot % mod;
    	int c = 1;
    	for (i = 0; i <= m; i++)
    	if (n - 1 >= i)
    	{
    		ans = (ans + (ll)f[i] * fac[i] % mod * c % mod * ksm(2, n - 1 - i)) % mod;
    		c = (ll)c * ksm(i + 1, mod - 2) % mod * (ll)(n - 1 - i) % mod;
    	}
    	else break;
    	ans = (ll)ans * n % mod * ksm(2, (ll)(n - 1) * (n - 2) / 2) % mod;
    	cout << ans << endl;
    	return 0;
    }
    
    
  • 相关阅读:
    Delphi实战中讲解FormCreate,FormShow,FormActivate
    delphi Try except on e:Exception do
    Delphi处理数据网格DBGrid的编辑框 获取还没有提交到数据集的字段文本
    delphi dbgrid中如何自动生成序号
    DBDateTimePicker;
    Delphi控件开发浅入深出(八)
    delphi中日期类型TDateTime使用总结
    在DBGrid录数据时,如何判断光标位置是在数据的最左或最右,如果是最左或最右则在按左右光标键时光标跳到上一格或下一格,如果是在数据中
    请问如何按Enter键让DBGrid的光标向右移以及换行?(0分)
    tdbgrid中用enter仿真tab键盘_delphi教程
  • 原文地址:https://www.cnblogs.com/cyf32768/p/12196466.html
Copyright © 2020-2023  润新知