zoukankan      html  css  js  c++  java
  • P4091 [HEOI2016/TJOI2016]求和

    P4091 [HEOI2016/TJOI2016]求和

    [f(n)=sum_{i=0}^{n}sum_{j=0}^{i}S_2(i,j)2^j(j!)\ =sum_{j=0}^{n}2^jj!sum_{i=0}^{n}S_2(i,j)\ =sum_{j=0}^{n}2^jj!sum_{i=0}^{n}dfrac{1}{j!}sum_{k=0}^{j}(-1)^{j-k}inom{j}{k}k^i\ =sum_{j=0}^{n}2^jsum_{i=0}^{n}sum_{k=0}^{j}(-1)^{j-k}inom{j}{k}k^i\ =sum_{j=0}^{n}2^jsum_{k=0}^{j}(-1)^{j-k}inom{j}{k}sum_{i=0}^{n}k^i\ =sum_{j=0}^{n}2^jsum_{k=0}^{j}(-1)^{j-k}inom{j}{k}dfrac{1-k^{n+1}}{1-k}\ =sum_{j=0}^{n}2^jj!sum_{k=0}^{j}dfrac{(-1)^{j-k}}{(j-k)!}dfrac{1-k^{n+1}}{(1-k)k!} ]

    水爆了,直接卷积就好了。等比数列记得判一下 (k=1) 就没有任何细节了。

    说一下为啥第二步把 (sumlimits_{i=j}^{n}) 换成 (sumlimits_{i=0}^{n}) 。正确性显然,加了一堆 (0)。 毕竟少一个变量比多一个变量方便吧。我一开始也是写从 (j) 开始的,最后一步发现没法卷积,审视了一下式子发现改掉边界就可以卷积了。所以其实我并不是一开始就这么算的,当然应该有人运气好或者直觉好一开始就这么写就可以少推几分钟。

    现在做出题都没有之前的兴奋感了,不知道是这题太水了还是我多项式做厌了。或许该停一阵子多项式?昨晚CF打炸了,根本没空开G这个数数题。其余部分感觉因为数数落下了,得去捡起来。

    const int N = 100005;
    const int M = N << 2;
    #define mod 998244353
    
    int n, A[M], B[M], ans;
    
    namespace math{
    int fac[N], ifc[N], inv[N];
    inline int qpow(int n, int k) {
    	int res = 1;
    	for (; k; k >>= 1, n = 1ll * n * n % mod)
    		if (k & 1) res = 1ll * n * res % mod;
    	return res;
    }
    void initmath(const int &n = N - 1) {
    	fac[0] = 1; rep(i, 1, n) fac[i] = 1ll * fac[i - 1] * i % mod;
    	ifc[n] = qpow(fac[n], mod - 2); per(i, n - 1, 0) ifc[i] = 1ll * ifc[i + 1] * (i + 1) % mod;
    	inv[1] =1; rep(i, 2, n) inv[i] = 1ll * inv[mod % i] * (mod - mod / i) % mod;
    }
    }
    using namespace math;
    
    namespace poly{
    int rev[M],lg,lim;
    void init_poly(const int &n) {
    	for (lg = 0, lim = 1; lim < n; ++lg, lim <<= 1);
    	for (int i = 0; i < lim; ++i) rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << (lg - 1));
    }
    void NTT(int *a, int op) {
    	for (int i = 0; i < lim; ++i)
    		if (i > rev[i]) swap(a[i], a[rev[i]]);
    	const int g = op ? 3 : inv[3];
    	for (int i = 1; i < lim; i <<= 1) {
    		const int wn = qpow(g, (mod - 1) / (i << 1));
    		for (int j = 0; j < lim; j += i << 1) {
    			int w0 = 1;
    			for (int k = 0; k < i; ++k, w0 = 1ll * w0 * wn % mod) {
    				const int X = a[j + k], Y = 1ll * w0 * a[i + j + k] % mod;
    				a[j + k] = (X + Y) % mod, a[i + j + k] = (X - Y + mod) % mod;
    			}
    		}
    	}
    	if (op) return; const int ilim = qpow(lim, mod - 2);
    	for (int i = 0; i < lim; ++i) a[i] = 1ll * a[i] * ilim % mod;
    }
    #define clr(a, n) memset(a, 0, sizeof(int) * (n))
    #define cpy(a, b, n) memcpy(a, b, sizeof(int) * (n))
    void poly_mul(int *f, int *g, int *ans, int n, int m) {
    	static int A[M], B[M]; init_poly(n + m);
    	cpy(A, f, n), clr(A + n, lim - n), NTT(A, 1);
    	cpy(B, g, m), clr(B + m, lim - m), NTT(B, 1);
    	for (int i = 0; i < lim; ++i) ans[i] = 1ll * A[i] * B[i] % mod;
    	NTT(ans, 0);
    }
    }
    
    signed main(){
    	initmath();
    	n = read();
    	for (int i = 0; i <= n; ++i) A[i] = i & 1 ? mod - ifc[i] : ifc[i];
    	for (int i = 0; i <= n; ++i){
    		if (i == 1) B[i] = n + 1;
    		else B[i] = 1ll * (qpow(i, n + 1) - 1) * qpow(1ll * fac[i] * (i - 1) % mod, mod - 2) % mod;
    	}
    	poly::poly_mul(A, B, A, n + 1, n + 1);
    	for (int i = 0, j = 1; i <= n; ++i, j = j * 2 % mod) ans = (ans + 1ll * j * fac[i] % mod * A[i] % mod) % mod;
    	printf("%d
    ", ans);
    	return 0;
    }
    
  • 相关阅读:

    80老婆如何制服老公的
    男人三件事
    抄袭了一篇散文,很适合现在的我.
    讲个小笑话
    博客的性别???测试下!!!
    十八禁 大全 [转载]
    [转载]男人你没房没车,我凭什么嫁给你!
    电脑维修 小产业高利润
    一美女莫名晕倒 被七男强行拖入森林
  • 原文地址:https://www.cnblogs.com/zzctommy/p/14282175.html
Copyright © 2011-2022 走看看