zoukankan      html  css  js  c++  java
  • P5641 【CSGRound2】开拓者的卓识

    P5641 【CSGRound2】开拓者的卓识

    像我这种菜鸡只能从组合意义考虑了,还要感谢 (color{black}{ exttt{c}}color{red}{ exttt{yn2006}}) 的指导。

    题目的公式比较鬼畜,考虑从 (a_i)(sum_{k,1,r}) 的贡献入手考虑。

    相当于我们要找有多少种“套娃”一样的区间包括 (i) 并且最大的那个是 ([1,r])

    (1le l_{k}le l_{k}lecdots icdotsle r_{k-2}le r_{k-1}le r) 的不同 ({[l_1,r_1],[l_2,r_2],cdots,[l_{k},r_{k}]}) 有几个

    显然左右端点是独立的。

    所以贡献为 (a_i imesinom{i+k-2}{k-1}inom{r-i+k-1}{k-1})

    意思就是每次左端点可以选择留在原地或者往左走,最多往左走 (i-1) 步。直接插板即可。

    最好先观察一下,不要直接暴力拆阶乘。

    发现下指标全是 (k-1) ,那么设 (p_i=inom{k-1+i}{k-1}),这个可以递推,考虑 (inom{n-1}{m} oinom{n}{m}) 的变化即可,即乘上 (dfrac{n}{n-m})

    所以

    (ans_i=sum_{j=1}^{i}a_j p_{j-1}p_{i-j})

    可以卷了。

    const int N=100005;
    const int M=600005;
    const int mod=998244353;
    int n,k,a[M],p[M],inv[N],rev[M],lg,lim;
    int qpow(int n,int k){int res=1;for(;k;k>>=1,n=1ll*n*n%mod)if(k&1)res=1ll*res*n%mod;return res;}
    void init(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 g,int op=0){
    	for (int i = 0; i < lim; ++ i) if (i > rev[i]) std::swap(a[i], a[rev[i]]);
    	for (int i = 1; i < lim; i <<= 1) {
    		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) {
    				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;int ilim = qpow(lim, mod - 2);
    	for (int i = 0; i < lim; ++ i) a[i] = 1ll * a[i] * ilim % mod;
    }
    signed main(){
    	n=read(),k=read();
    	for(int i=1;i<=n;++i)a[i]=read();
    	p[0]=1,inv[1]=1;
    	for(int i=2;i<=n;++i)inv[i]=1ll*(mod-mod/i)*inv[mod%i]%mod;
    	for(int i=1;i<=n;++i)p[i]=1ll*p[i-1]*(k-1+i)%mod*inv[i]%mod,a[i]=1ll*a[i]*p[i-1]%mod;
    	init(n<<1),NTT(a,3),NTT(p,3);
    	for(int i=0;i<lim;++i)a[i]=1ll*a[i]*p[i]%mod;
    	NTT(a,qpow(3,mod-2),1);
    	for(int i=1;i<=n;++i)printf("%d ",a[i]);
    	return 0;
    }
    
  • 相关阅读:
    通过hmc启动lpar的终端
    修复LVM手记
    通过VMLibrary在client partition上安装AIX全程实录
    【转】通过VIOS实现AIX系统的网络虚拟化
    rhel 6 启动流程分析(/etc/inittab)
    Linux中tty、pty、pts的概念区别
    Shell中while循环的done 后接一个重定向<
    搭建dns服务器时报错error: bind: address already in use
    关于 smit mktcpip 和smit chinet 的区别
    博客园博客停更(本博客收集本人于2018年之前的博客,2018年之后的博客统一发布在CSDN上)
  • 原文地址:https://www.cnblogs.com/zzctommy/p/14191409.html
Copyright © 2011-2022 走看看