• P5641. 【CSGRound2】开拓者的卓识


    \(\text{Solution}\)

    推柿子比较套路,考虑每一个\(a_i\)\(sum_{k,1,j}\)的贡献即可。
    看看\(sum\)是如何转移的

    \[a_i \implies sum_{1,l_1,r_1} \implies sum_{2,l_2,r_2} \implies ... \implies sum_{k,l_k,r_k} \]

    其中\(1 \le l_k \le l_{k - 1} \le ... \le i \le ... \le r_k \le j\)
    那我们只需考虑\(l,r\)组合的方案数即可,用插板法计算为

    \[\binom{i + k - 2}{k - 1}\binom{j - i + k - 1}{k - 1} \]

    所以

    \[sum_{k,1,j} = \sum_{i = 1}^{j}a_i\binom{i + k - 2}{k - 1}\binom{j - i + k - 1}{k - 1} \]

    \[A_i = a_{i}\binom{i + k - 2}{k - 1} = \frac{a_ik^{\overline{i - 1}}}{(i - 1)!},B_i = \binom{i + k - 1}{k - 1} = \frac{k^{\overline{i}}}{i!} \]

    这样可以快速计算\(A_i,B_i\)

    \[sum_{k,1,j} = \sum_{i + (j - i) = j}A_iB_{j - i} \]

    这样就是卷积了。

    \(\text{Code}\)

    #include<cstdio>
    #include<algorithm>
    #define LL long long
    using namespace std;
    const int N = 1e5 + 5,P = 998244353;
    int n,rev[N * 3]; LL k,a[N],b[N],f[N * 3],g[N * 3];
    
    LL fpow(LL x,LL y)
    {
    	LL res = 1;
    	for (; x; x >>= 1,y = y * y % P)
    		if (x & 1) res = res * y % P;
    	return res;	
    }
    void NTT(LL *f,int len,int fl)
    {
    	if (len == 1) return;
    	for (int i = 0; i < len; i++)
    		if (i < rev[i]) swap(f[i],f[rev[i]]);
    	for (int l = 1; l < len; l <<= 1)
    	{
    		LL I = fpow((P - 1) / (l << 1),3);
    		if (fl == -1) I = fpow(P - 2,I);
    		for (int i = 0; i < len; i += (l << 1))
    		{
    			LL W = 1;
    			for (int j = 0; j < l; j++,W = W * I % P)
    			{
    				LL x = f[i + j],y = W * f[i + j + l] % P;
    				f[i + j] = (x + y) % P,f[i + j + l] = (x - y + P) % P;
    			}
    		}
    	}
    }
    int main()
    {
    	scanf("%d%lld",&n,&k);
    	for (int i = 1; i <= n; i++) scanf("%lld",&a[i]);
    	b[0] = 1;
    	for (int i = 1; i <= n; i++) b[i] = b[i - 1] * (k + i - 1) % P * fpow(P - 2,i) % P;
    	for (int i = 1; i <= n; i++) f[i] = a[i] * b[i - 1] % P;
    	for (int i = 1; i <= n; i++) g[i] = b[i]; g[0] = 1;
    	
    	int len = 1,bit = 0;
    	while (len <= n << 1) len <<= 1,bit++;
    	for (int i = 1; i < len; i++) rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << bit - 1);
    	
    	NTT(f,len,1),NTT(g,len,1);
    	for (int i = 0; i < len; i++) f[i] = f[i] * g[i] % P;
    	NTT(f,len,-1); LL inv = fpow(P - 2,len);
    	for (int i = 1; i <= n; i++) printf("%lld ",inv * f[i] % P); 
    } 
    
  • 相关阅读:
    CentOS 6.3下Samba服务器的安装与配置(转)
    利用香蕉派自制电视盒子
    利用arduino制作瓦力万年历-1.0
    arduino:int & double 转string 适合12864下使用
    centos 6.X下建立arduino开发环境
    树莓派学习笔记(7):利用bypy实现树莓派NAS同步百度云
    直接插入排序
    直接选择排序
    快速排序算法
    git 分支管理 推送本地分支到远程分支等
  • 原文地址:https://www.cnblogs.com/nibabadeboke/p/16478383.html
Copyright © 2020-2023  润新知