zoukankan      html  css  js  c++  java
  • 洛谷P4351 [CERC2015]Frightful Formula【组合计数】

    [CERC2015]Frightful Formula

    Description

    定义一个矩阵 (F),给定其第一行和第一列,其他位置将通过递推方式给出,具体的:

    [F_{i,j}=aF_{i,j-1}+bF_{i-1,j}+c ]

    (F(n,n))

    (nle 2 imes 10^5)

    Solution

    首先考虑 (c=0) 的情况,此时原问题可以看作从第二行第二列出发,只能向右或向下走且向右走的权值为 (a),向左走的权值为 (b) 时所有方案的权值积之和。枚举起点,容易写出贡献就是:

    [sum_{i=2}^{n}l_iinom{2n-2-i}{n-2}a^{n-1}b^{n-i}+sum_{i=2}^{n}t_iinom{2n-2-i}{n-2}a^{n-i}b^{n-1} ]

    这一部分可以暴力 (mathcal O(n)) 计算,接下来考虑 (c) 对答案的贡献,枚举 (c) 在哪一个位置出现,那么它的贡献就是从这个位置到 ((n,n)) 的所有方案的权值积:

    [csum_{i=2}^{n}sum_{j=2}^{n}inom{2n-i-j}{n-i}a^{n-j}b^{n-i}\ =csum_{i=2}^{n}dfrac{b^{n-i}}{(n-i)!}sum_{j=2}^{n}dfrac{a^{n-j}(2n-i-j)!}{(n-j)!} ]

    这就是一个减法卷积,由于模数为 (10^6+3) ,所以需要使用 (MTT)

    略微有点卡常,考虑优化,回到 (c) 的柿子,改为枚举 (2n-i-j) 试试?

    [csum_{t=0}^{2n-4}sum_{i=max(0,t-n+2)}^{n-2}inom{t}{i}a^{t-i}b^i ]

    我们想直接大力二项式定理,但好像上标下标不太对,考虑分 (tle n-2)(t>n-2) 分别讨论:

    (tle n-2):

    [egin{aligned} &=csum_{t=0}^{n-2}sum_{i=0}^{t}inom{t}{i}a^{t-i}b^i\ &=csum_{t=0}^{n-2}(a+b)^t end{aligned} ]

    (t>n-2):

    [egin{aligned} &=csum_{t=n-1}^{2n-4}sum_{i=t-n+2}^{n-2}inom{t}{i}a^{t-i}b^i\ end{aligned} ]

    (g_t=sum_{i=t-n+2}^{n-2}dbinom{t}{i}a^{t-i}b^i)

    有:

    [egin{aligned} g_t&=sum_{i=t-n+2}^{n-2}(inom{t-1}{i-1}+inom{t-1}{i})a^{t-i}b^i\ &=asum_{i=t-n+2}^{n-2}inom{t-1}{i}a^{(t-1)-i}b^i+bsum_{i=t-n+2}^{n-2}inom{t-1}{i-1}a^{(t-1)-(i-1)}b^{i-1}\ end{aligned} ]

    这玩意很像是 ((a+b)g_{t-1}),但是前者的上下界为 ([t-n+2,n-2]),后者为 ([t-n+1,n-3]),距离 ([t-n+1,n-2]) 都有差距,需要减去多出的部分:

    [g_t=(a+b)g_{t-1}-inom{t-1}{t-n+1}a^{n-1}b^{t-n+1}-inom{t-1}{n-2}a^{t-n+1}b^{n-1}\ ]

    于是直接 (mathcal O(n)) 递推即可。复杂度 (mathcal O(n))

    Code

    #include<bits/stdc++.h>
    using namespace std;
    const int N=4e5+10,mod=1e6+3;
    int n,a,b,c,l[N],t[N],base[N],jc[N],pwa[N],pwb[N],f[N];
    inline int ksm(int x,int y){
    	int ret=1;
    	for(;y;y>>=1,x=1ll*x*x%mod) if(y&1) ret=1ll*ret*x%mod;
    	return ret;
    }
    inline void init(int n){
    	base[0]=1;
    	for(int i=1;i<=n;++i) base[i]=1ll*base[i-1]*i%mod;
    	jc[n]=ksm(base[n],mod-2);
    	for(int i=n-1;i>=0;--i) jc[i]=1ll*jc[i+1]*(i+1)%mod;
    	pwa[0]=1;pwb[0]=1;
    	for(int i=1;i<=n;++i) pwa[i]=1ll*pwa[i-1]*a%mod,pwb[i]=1ll*pwb[i-1]*b%mod;
    }
    inline int binom(int x,int y){if(x<y) return 0;return 1ll*base[x]*jc[y]%mod*jc[x-y]%mod;}
    inline void inc(int &x,int y){x=(x+y>=mod)?x+y-mod:x+y;}
    inline int dec(int x,int y){return (x-y<0)?x-y+mod:x-y;}
    int main(){
    	scanf("%d%d%d%d",&n,&a,&b,&c);
    	init(n<<1);
    	int ans=0;
    	for(int i=1;i<=n;++i){
    		scanf("%d",&l[i]);
    		if(i>=2) ans=(ans+1ll*l[i]*binom(n-2+n-i,n-2)%mod*pwa[n-1]%mod*pwb[n-i])%mod;
    	}
    	for(int i=1;i<=n;++i){
    		scanf("%d",&t[i]);
    		if(i>=2) ans=(ans+1ll*t[i]*binom(n-2+n-i,n-2)%mod*pwb[n-1]%mod*pwa[n-i])%mod;
    	}
    	int ret=0;
    	for(int t=0,pw=1;t<=n-2;++t,pw=1ll*pw*(a+b)%mod)
    		inc(ret,pw);
    	for(int t=n-1;t<=2*n-4;++t){
    		if(t==n-1){
    			f[n-1]=0;
    			for(int i=1;i<=n-2;++i) f[n-1]=(f[n-1]+1ll*binom(n-1,i)*pwa[n-1-i]%mod*pwb[i])%mod;
    		}
    		else{
    			f[t]=1ll*f[t-1]*(a+b)%mod;
    			f[t]=dec(f[t],1ll*binom(t-1,t-n+1)*pwa[n-1]%mod*pwb[t-n+1]%mod);
    			f[t]=dec(f[t],1ll*binom(t-1,n-2)*pwb[n-1]%mod*pwa[t-n+1]%mod);
    		}
    		inc(ret,f[t]);
    	}
    	ans=(ans+1ll*ret*c)%mod;
    	printf("%d
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    安装Hadoop单机版
    Linux的en33没有IP地址
    idea导入spring源码
    CSS 选择器之基础选择器
    CSS 简介和代码风格
    JavaScript 中 双感叹号 !! 的作用
    VS Code 中的settings.js 配置
    项目中使用 vuex 实现(状态)数据共享
    VS Code 相关设置
    Node.js 的简单了解
  • 原文地址:https://www.cnblogs.com/tqxboomzero/p/14978696.html
Copyright © 2011-2022 走看看