• 【BZOJ4555】【TJOI2016】【HEOI2016】求和


    题目

    传送门

    解法

    我们可以用容斥来求第二类斯特林数

    我们知道, 第二类斯特林数(S(n, k))(n)个元素放进(k)个无标号的盒子里, 不可以含有空的。 于是我们可以考虑可以含有空的,且盒子有标号, 情况下的数量, 这明显是(sumlimits_{j = 0}^{k}{k choose j}(k-j)^n)

    于是, 根据容斥原理可得:(S(n, k) = frac{1}{k!}sum_{j = 0}^{k}(k-j)^n{k choose j}(-1)^i)

    于是

    [egin{aligned} &sum_{i = 0}^{n}sum_{j = 0}^{i}S(i, j)\ &=sum_{i = 0}^{n}sum_{j = 0}^{i}S(i, j)\ &=sum_{i = 0}^{n}sum_{j = 0}^{n}2^jj!{frac{1}{j!}}sum_{k = 0}^{j}(j-k)^i(-1)^j{j choose k}\ &= sum_{i = 0}^{n}sum_{j = 0}^{n}2^jsum_{k = 0}^{j}(j-k)^i(-1)^jfrac{j!}{k!(j-k)!}\ &= sum_{i = 0}^{n}sum_{j = 0}^{n}2^jsum_{k = 0}^{j}(j-k)^i(-1)^jfrac{j!}{k!(j-k)!}\ &= sum_{i = 0}^{n}sum_{j = 0}^{n}2^jj!sum_{k = 0}^{j}(j-k)^i(-1)^jfrac{1}{k!(j-k)!}\ &= sum_{i = 0}^{n}sum_{j = 0}^{n}2^jj!sum_{k = 0}^{j}(-1)^jfrac{(j-k)^i}{k!(j-k)!}\ &= sum_{i = 0}^{n}sum_{j = 0}^{n}2^jj!sum_{k = 0}^{j}(-1)^jfrac{1}{k!}frac{(j-k)^i}{(j-k)!} \ &= sum_{j = 0}^{n}2^jj!sum_{k = 0}^{j}(-1)^jfrac{1}{k!}sum_{i = 0}^{n}frac{(j-k)^i}{(j-k)!} end{aligned} ]

    于是, 这里出现了一个感人肺腑的卷积

    我们设(a(x) = frac{1}{x!}(-1)^x), (b(x) = sum_{k = 0}^{n}{k^{x}over k!})

    于是答案是(sumlimits_{j = 0}^{n}sumlimits_{k = 0}^{j}a(k)b(j-k))

    (b)可以用等比数列求和公式求出

    代码

    #include <iostream>
    #include <cstdlib>
    #include <cstdio>
    #include <cstdlib>
    #include <algorithm>
    
    using namespace std;
    
    typedef long long LL;
    
    const LL mod = 998244353LL;
    
    const int N = 400010;
    
    inline LL power(LL a, LL n, LL mod)
    {	LL Ans = 1;
    	a %= mod;
    	while (n)
    	{	if (n & 1) Ans = (Ans * a) % mod;
    		a = (a * a) % mod;
    		n >>= 1;
    	}
    	return Ans;
    }
    
    inline LL Plus(LL a, LL b) { return a + b > mod ? a + b - mod : a + b; }
    
    inline LL Minus(LL a, LL b) { return a - b < 0 ? a - b + mod : a - b; }
    
    struct Mul
    {	int Len, Bit;
    
    	LL wn[N];
    
    	int rev[N];
    
    	void getReverse()
    	{	for (int i = 0; i < Len; i++)
    			rev[i] = (rev[i>>1] >> 1) | ((i&1) * (Len >> 1));
    	}
    
    	void NTT(LL * a, int opt)
    	{	getReverse();
    		for (int i = 0; i < Len; i++)
    			if (i < rev[i]) swap(a[i], a[rev[i]]);
    		int cnt = 0;
    		for (int i = 2; i <= Len; i <<= 1)
    		{	cnt++;
    			for (int j = 0; j < Len; j += i)
    			{	LL w = 1LL;
    				for (int k = 0; k < (i>>1); k++)
    				{	LL x = a[j + k];
    					LL y = (w * a[j + k + (i>>1)]) % mod;
    					a[j + k] = Plus(x, y);
    					a[j + k + (i>>1)] = Minus(x, y);
    					w = (w * wn[cnt]) % mod;
    				}
    			}
    		}
    		if (opt == -1)
    		{	reverse(a + 1, a + Len);
    			LL num = power(Len, mod-2, mod);
    			for (int i = 0; i < Len; i++)
    				a[i] = (a[i] * num) % mod;
    		}
    	}
    
    	void getLen(int l)
    	{	Len = 1, Bit = 0;
    		for (; Len <= l; Len <<= 1) Bit++;
    	}
    
    	void init()
    	{	for (int i = 0; i < 23; i++)
    			wn[i] = power(3, (mod-1) / (1LL << i), mod);
    	}
    } Calc;
    
    LL fac[N], ifac[N];
    
    LL A[N], B[N], C[N];
    
    int main()
    {	int n;
    	scanf("%d", &n);
    	fac[0] = 1;
    	for (int i = 1; i <= n; i++)
    		fac[i] = fac[i-1] * i % mod;
    	ifac[n] = power(fac[n], mod-2, mod);
    	for (int i = n-1; i >= 0; i--)
    		ifac[i] = ifac[i+1] * (i+1) % mod;
    	for (int i = 0; i <= n; i++)
    		A[i] = (i & 1 ? Minus(mod, 1) : 1) * ifac[i] % mod;
    	B[0] = 1;
    	B[1] = n + 1;
    	for (int i = 2; i <= n; i++)
    		B[i] = (power(i, n+1, mod) + mod - 1) % mod * power(i-1, mod-2, mod) % mod * ifac[i] % mod;
    	Calc.init();
    	Calc.getLen(n * 2 + 1);
    	Calc.NTT(A, 1);
    	Calc.NTT(B, 1);
    	for (int i = 0; i < Calc.Len; i++)
    		C[i] = A[i] * B[i] % mod;
    	Calc.NTT(C, -1);
    	LL Ans = 0;
    	for (int i = 0; i <= n; i++)
    		Ans = Plus(Ans, (power(2LL, i, mod) * fac[i] % mod * C[i] % mod));
    	printf("%lld
    ", Ans);
    	return 0;
    }
    
  • 相关阅读:
    PAT 乙级真题 1013.组个最小数
    PAT 乙级真题 1012.D进制的A+B
    PAT 乙级真题 1011.个位数统计
    PAT 乙级真题 1010.月饼
    PAT 乙级真题 1009.1019.数字黑洞
    PAT 乙级真题 1008.锤子剪刀布
    PAT 乙级真题 1007.A除以B
    PAT 乙级真题 1006.1016.部分A+B
    C++自定义sort函数
    VS2017如何使用scanf函数
  • 原文地址:https://www.cnblogs.com/2016gdgzoi509/p/9424872.html
Copyright © 2020-2023  润新知