• 【UNR #3】百鸽笼


    题面

    题解

    假设每一列塞满了之后还可以继续塞(只是没有用),事实上和原问题一致。

    所以说,对于一个序列,如果第 (i) 列有空,说明恰好有 (a_i)(i)(geq a_j)(j (j eq i)) 且以 (i) 结尾。

    (G_i(x) = frac {x^i} {n^i i!}, S_i(x) = sum_{j leq i} G_j(x)),那么可以写出第 (i) 列的 EGF:

    [F_i(x) = frac {G_{a_i - 1}(x)} {n} prod_{j eq i} sum_{k geq a_j} G_k(x) ]

    而第 (i) 列的答案就是

    [mathrm{ans}_i = sum_{j geq 0} j![x^j]F_i(x) ]

    由于 (S_{infty} (x) = e^{frac xn}),所以

    [F_i = frac {G_{a_i - 1}} {n} prod_{j eq i} (e^{frac xn} - S_{a_j - 1}) ]

    背包可以得出 (F_i = sum_{u, v} f_{u, v} e^{frac {ux}n} x^v),一个 (e^{frac {ux}n} x^v) 的贡献为 (sum_{i geq 0} (frac un)^i frac {(v + i)!} {i!} = v!sum_{i geq 0} (frac un)^i inom {v + i} {i} = v! (frac {n} {n - u})^{v + 1}),那么就可以直接计算了。

    代码

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <vector>
    #define file(x) freopen(#x".in", "r", stdin), freopen(#x".out", "w", stdout)
    
    inline int read()
    {
    	int data = 0, w = 1; char ch = getchar();
    	while (ch != '-' && (ch < '0' || ch > '9')) ch = getchar();
    	if (ch == '-') w = -1, ch = getchar();
    	while (ch >= '0' && ch <= '9') data = data * 10 + (ch ^ 48), ch = getchar();
    	return data * w;
    }
    
    const int N(35), Mod(998244353);
    inline int upd(const int &x) { return x + (x >> 31 & Mod); }
    int fastpow(int x, int y)
    {
    	int ans = 1;
    	for (; y; y >>= 1, x = 1ll * x * x % Mod)
    		if (y & 1) ans = 1ll * ans * x % Mod;
    	return ans;
    }
    
    int n, m, a[N], f[N][N * N], h[N][N * N], fac[N * N], inv[N * N], rev[N * N];
    void Mul(int x)
    {
    	static int g[N][N * N];
    	for (int i = 0; i <= n; i++) std::memset(g[i], 0, (m + 1) << 2);
    	for (int i = 0; i <= n; i++)
    		for (int j = 0; j <= m; j++)
    		{
    			if (i) g[i][j] = f[i - 1][j];
    			for (int k = 0; k < a[x] && k <= j; k++)
    				g[i][j] = upd(g[i][j] - 1ll * f[i][j - k] * rev[k] % Mod * inv[k] % Mod);
    		}
    	for (int i = 0; i <= n; i++) std::memcpy(f[i], g[i], (m + 1) << 2);
    }
    
    void Div(int x)
    {
    	static int g[N][N * N];
    	for (int i = 0; i <= n; i++) std::memcpy(g[i], f[i], (m + 1) << 2);
    	for (int i = 0; i <= n; i++)
    		for (int j = 0; j <= m; j++)
    		{
    			if (i) g[i][j] = upd(g[i][j] - g[i - 1][j]);
    			for (int k = 1; k < a[x] && k <= j; k++)
    				g[i][j] = (g[i][j] + 1ll * g[i][j - k] * rev[k] % Mod * inv[k]) % Mod;
    			g[i][j] = upd(-g[i][j]);
    		}
    	for (int i = 0; i <= n; i++) std::memcpy(f[i], g[i], (m + 1) << 2);
    }
    
    void calc(int x)
    {
    	for (int i = 0; i <= n; i++) std::memset(h[i], 0, (m + 1) << 2);
    	for (int i = 0; i <= n; i++)
    		for (int j = a[x] - 1; j <= m; j++)
    			h[i][j] = 1ll * f[i][j - a[x] + 1] * rev[a[x]] % Mod * inv[a[x] - 1] % Mod;
    }
    
    int main()
    {
    #ifndef ONLINE_JUDGE
    	file(cpp);
    #endif
    	n = read(), f[0][0] = fac[0] = rev[0] = 1, rev[1] = fastpow(n, Mod - 2);
    	for (int i = 1; i <= n; i++) m += (a[i] = read());
    	for (int i = 1; i <= m; i++) fac[i] = 1ll * fac[i - 1] * i % Mod;
    	for (int i = 2; i <= m; i++) rev[i] = 1ll * rev[i - 1] * rev[1] % Mod;
    	inv[m] = fastpow(fac[m], Mod - 2);
    	for (int i = m; i; i--) inv[i - 1] = 1ll * inv[i] * i % Mod;
    	for (int i = 1; i <= n; i++) Mul(i);
    	for (int i = 1, ans; i <= n; i++)
    	{
    		Div(i), calc(i), ans = 0;
    		for (int j = 0; j < n; j++) for (int k = 0; k <= m; k++)
    			ans = (ans + 1ll * fastpow(1ll * n * fastpow(n - j, Mod - 2) % Mod, k + 1) * fac[k] % Mod * h[j][k]) % Mod;
    		printf("%d ", ans), Mul(i);
    	}
    	return 0;
    }
    
  • 相关阅读:
    pycharm调试时出现十分缓慢,变量数据没法预览的解决办法
    gitignore设置失效的问题
    存储过程计算两个时间段的请假天数
    Vue 多层级目录拖动排序
    vue 动态插入渲染html
    Vue:eliment-ui el-tree动态加载更新
    Angular2+ iframe跨域调用父页面js
    Angular2.0+动态绑定html文本
    Angular2.0+开发 -实现部门树形结构
    Angular2.0+开发(1)-WebStorm配置及第一个Hello World
  • 原文地址:https://www.cnblogs.com/cj-xxz/p/14407361.html
Copyright © 2020-2023  润新知