• 题解-P5162 WD与积木[*easy]


    由于要算的是概率,所以要算的东西分成两个部分 :所有情况的答案总和 和 情况数量。

    考虑一层积木的 EGF(G(x) = e^x - 1)

    那么 (k) 层积木的 EGF 就是 ((e^x - 1)^k)

    我们要算的第二个东西的 EGF 就是 (sumlimits_{i = 1}^{n} G(x)^k = frac{G(x)^{n + 1} - G(x)}{G(x) - 1} equiv frac{G(x)}{G(x) - 1})。多项式求逆即可。

    我们要算的第一个东西的是 EGF(sumlimits_{i = 1}^n i G(x)^i)

    [sumlimits_{i = 1}^n sumlimits_{j=1}^{i} G(x)^i ]

    [sumlimits_{j=1}^{n} sumlimits_{i = j}^n G(x)^i ]

    [sumlimits_{j=1}^{n} frac{G(x)^{n + 1} - G(x)^j}{G(x) - 1} ]

    考虑到 (G(x)^{n + 1} equiv 0),所以是

    [- frac{1}{G(x) - 1} sumlimits_{j=1}^{n} G(x)^j ]

    [- frac{1}{G(x) - 1} frac{G(x)^{n + 1} - G(x)}{G(x) - 1} ]

    [- frac{1}{G(x) - 1} frac{G(x)^{n + 1} - G(x)}{G(x) - 1} ]

    [frac{G(x)}{(G(x) - 1)^2} ]

    代码:

    #include<bits/stdc++.h>
    #define L(i, j, k) for(int i = j, i##E = k; i <= i##E; i++) 
    #define R(i, j, k) for(int i = j, i##E = k; i >= i##E; i--)
    #define ll long long
    #define ull unsigned long long 
    #define db double
    #define pii pair<int, int>
    #define mkp make_pair
    using namespace std;
    const int mod = 998244353, G = 3, iG = (mod + 1) / G, N = 3e5, MAXN = 1e5;
    int qpow(int x, int y = mod - 2) {
    	int res = 1;
    	for(; y; x = (ll) x * x % mod, y >>= 1) if(y & 1) res = (ll) res * x % mod;
    	return res;
    }
    int lim, pp[N];
    void poinit() { L(i, 0, lim - 1) pp[i] = ((pp[i >> 1] >> 1) | ((i & 1) * (lim >> 1))); }
    void up(int len) { lim = 1; for(; lim <= len; lim <<= 1); }
    void NTT(int *f, int flag) {
    	L(i, 0, lim - 1) if(pp[i] < i) swap(f[pp[i]], f[i]);
    	for(int i = 2; i <= lim; i <<= 1) 
    		for(int j = 0, l = (i >> 1), ch = qpow(flag == 1 ? G : iG, (mod - 1) / i); j < lim; j += i) {
    			for(int k = j, now = 1; k < j + l; k ++) {
    				int pa = f[k], pb = (ll) f[k + l] * now % mod;
    				f[k] = (pa + pb) % mod, f[k + l] = (pa - pb + mod) % mod, now = (ll) now * ch % mod;
    			}
    		}
    	if(flag == -1) {
    		int ilim = qpow(lim);
    		L(i, 0, lim - 1) f[i] = (ll) f[i] * ilim % mod;
    	}
    }
    int sav[N];
    void cle(int *f) { fill(f, f + lim, 0); }
    void inv(int *f, int *g, int len) {
    	if(len == 1) return g[0] = qpow(f[0]), void();
    	inv(f, g, (len + 1) >> 1), up(len << 1), poinit(), cle(sav), copy(f, f + len, sav), NTT(sav, 1), NTT(g, 1);
    	L(i, 0, lim - 1) g[i] = (ll) g[i] * (2 + mod - (ll) sav[i] * g[i] % mod) % mod;
    	NTT(g, -1), fill(g + len, g + lim, 0);
    }
    int fac[N], ifac[N];
    void minit(int x) {
    	fac[0] = 1;
    	L(i, 1, x)  fac[i] = (ll) fac[i - 1] * i % mod;
    	ifac[x] = qpow(fac[x]);
    	R(i, x, 1) ifac[i - 1] = (ll) ifac[i] * i % mod;
    }
    int g[N], f[N], ans[N];
    int main() {
    	ios::sync_with_stdio(false);
    	cin.tie(0), cout.tie(0);
    	minit(MAXN);
    	L(i, 0, MAXN) g[i] = ifac[i]; 
    	g[0] = mod - 1, inv(g, ans, MAXN + 1), g[0] = 0, up(MAXN * 2), poinit(), NTT(ans, 1), NTT(g, 1);
    	L(i, 0, lim - 1) f[i] = mod - (ll) g[i] * ans[i] % mod, ans[i] = (ll) ans[i] * ans[i] % mod;
    	NTT(f, -1), NTT(ans, -1), fill(ans + MAXN + 1, ans + lim, 0), NTT(ans, 1);
    	L(i, 0, lim - 1) ans[i] = (ll) ans[i] * g[i] % mod;
    	NTT(ans, -1);
    	int T, n; cin >> T;
    	while(T--) cin >> n, cout << (ll) ans[n] * qpow(f[n]) % mod << endl;
    	return 0;
    } 
    
  • 相关阅读:
    sql中table用法
    sql group by
    C#excel导入
    手写简单JDBC
    连接池+事务
    mysql+jdbc
    mysql(多表)
    jsp标签+jstl
    页面跳转+路径问题
    ajax 动态获取数据库中的值
  • 原文地址:https://www.cnblogs.com/zkyJuruo/p/14285534.html
Copyright © 2020-2023  润新知