zoukankan      html  css  js  c++  java
  • 【清华集训2016】如何优雅地求和

    首先,这种形式肯定是把组合数消掉一点,然后后面再二项式定理处理一下。但是怎么搞呢?

    开始尝试了拉格朗日插值,但是有一项非常毒瘤。(我甚至少抄一项推出了 (O(n)) 的式子……)

    要消掉组合数一定是与阶乘有关的形式。连续点值启发着我们使用下降幂。众所周知,点值转下降幂系数只需要卷上一个 (e^{-x}) 即可。

    这时候考虑只用式子里代入下降幂:

    [egin{align*} & sum_{k=0}^n k^{underline{m}} inom{n}{k} x^k left( 1 - x ight) ^ {n - k} \ =& sum_{k=0}^n frac{k!}{left(k-m ight)!} frac{n!}{k!left(n-k ight)!} x^k left( 1 - x ight) ^ {n - k} \ =& sum_{k=0}^n frac{n!}{left(n-m ight)!} frac{left(n - m ight)!}{left(k-m ight)!left(n-k ight)!} x^k left( 1 - x ight) ^ {n - k} \ =& n^{underline{m}} x^m sum_{k=0}^n inom{n - m}{n-k} x^{k-m} left( 1 - x ight) ^ {n - k} \ =& n^{underline{m}} x^m sum_{k=0}^n left(1 - x + x ight) ^ {n - m} \ =& n^{underline{m}} x^m end{align*} ]

    容易计算。所以瓶颈就在转下降幂。如果实现好的话 (O(n^2)) 也是可以的。

    #include <bits/stdc++.h>
    
    const int mod = 998244353;
    const int MAXN = 20010; 
    typedef long long LL;
    void reduce(int & x) { x += x >> 31 & mod; }
    int mul(int a, int b) { return (LL) a * b % mod; }
    int fastpow(int a, int b) {
    	int res = 1; a %= mod;
    	for (; b; b >>= 1, a = mul(a, a)) if (b & 1) res = mul(res, a);
    	return res;
    }
    int A[MAXN], inv[MAXN], fac[MAXN], B[MAXN];
    int n, m, X;
    int inv2[MAXN];
    int main() {
    	inv[0] = inv[1] = fac[0] = fac[1] = 1;
    	for (int i = 2; i != MAXN; ++i) {
    		fac[i] = mul(fac[i - 1], i);
    		inv[i] = mul(inv[mod % i], mod - mod / i);
    	}
    	inv2[0] = 1, inv2[1] = mod - 1;
    	for (int i = 2; i != MAXN; ++i) {
    		inv[i] = mul(inv[i - 1], inv[i]);
    		reduce(inv2[i] = i & 1 ? mod - inv[i] : inv[i]);
    	}
    	std::cin >> n >> m >> X; ++m;
    	for (int i = 0; i < m; ++i) std::cin >> A[i], A[i] = mul(A[i], inv[i]);
    	for (int i = 0, t; i < m; ++i)
    		for (int j = 0; i + j < m; ++j)
    			reduce(B[i + j] += (LL) A[i] * inv2[j] % mod - mod);
    	for (int i = 0; i < m; ++i) A[i] = mul(A[i], fac[i]);
    	int now = 1, ans = 0;
    	for (int i = 0; i < m; ++i) {
    		reduce(ans += (LL) fastpow(X, i) * now % mod * B[i] % mod - mod);
    		now = mul(now, n - i);
    	}
    	std::cout << ans << std::endl;
    	return 0;
    }
    
  • 相关阅读:
    就这样吧
    搞了个1.0版本,名字和预定的一样改成OIFaQ了
    算了,总结一下教训
    我刚经历了人生中第一次版本回滚,目前感觉良好,请党和人民放心
    这有点爽的
    我决定出1.0的时候改名叫OIFaQ
    换个SSD把D盘弄飞了
    算是交代一下这三天的空白
    构建之法读书笔记03
    构建之法读书笔记02
  • 原文地址:https://www.cnblogs.com/daklqw/p/11623895.html
Copyright © 2011-2022 走看看