zoukankan      html  css  js  c++  java
  • Codeforces 708E. Student's Camp 题解

    题目链接:E. Student's Camp

    题目大意:洛谷


    题解:首先考虑最朴素的转移即设 (f_{i,l,r}) 表示到了第 (i) 层,前面全部连通,第 (i) 层剩余的砖块是 ([l,r]) 的方案数,然后考虑容斥转移,令 (P_{l,r}) 表示一行中恰好剩下 ([l,r]) 中的砖块的概率,然后就可以得到(f_{i,l,r}=P_{l,r}(sum f_{i-1,l^{'},r^{'}}-sum_{r^{'}<l} f_{i-1,l^{'},r_{'}}-sum_{l_{'}>r}f_{i-1,l^{'},r^{'}}))

    然后把整个式子整理一下,因为容易发现后面的两个式子是对称的,所以我们可以将第三个式子翻转一下变成和第二个式子一样的形式,再设 (s_{i,r}=sum_{l<=r}f_{i,l,r}) , (f_i=sum f_{i,l,r}=sum s_{i,r}) ,然后上面的转移就可以全部用 (s)(f)·来表示,然后再将整个式子用 (s,f) 来表示,来推出仅和 (s,f) 有关的递推式,然后再考虑用前缀和优化一下,这样的话时间复杂度就变成了(O(nm))的。

    代码:

    #include <cstdio>
    int quick_power(int a,int b,int Mod){
    	int ans=1;
    	while(b){
    		if(b&1){
    			ans=1ll*ans*a%Mod;
    		}
    		b>>=1;
    		a=1ll*a*a%Mod;
    	}
    	return ans;
    }
    int min(int a,int b){
    	return a<b?a:b;
    }
    const int Maxn=1500;
    const int Maxk=100000;
    const int Mod=1000000007;
    int n,m;
    int p;
    int k;
    int frac[Maxk+5],inv_f[Maxk+5];
    int g[Maxn+5],q[Maxn+5];
    void init(){
    	frac[0]=1;
    	for(int i=1;i<=Maxk;i++){
    		frac[i]=1ll*frac[i-1]*i%Mod;
    	}
    	inv_f[Maxk]=quick_power(frac[Maxk],Mod-2,Mod);
    	for(int i=Maxk-1;i>=0;i--){
    		inv_f[i]=1ll*inv_f[i+1]*(i+1)%Mod;
    	}
    }
    int C(int n,int m){
    	return 1ll*frac[n]*inv_f[m]%Mod*inv_f[n-m]%Mod;
    }
    int f[Maxn+5][Maxn+5],s[Maxn+5][Maxn+5],h[Maxn+5][Maxn+5];
    int main(){
    	init();
    	scanf("%d%d",&n,&m);
    	scanf("%d%d",&p,&k);
    	p=1ll*p*quick_power(k,Mod-2,Mod)%Mod;
    	scanf("%d",&k);
    	for(int i=0;i<=min(m,k);i++){
    		g[i]=1ll*C(k,i)*quick_power(p,i,Mod)%Mod*quick_power((1-p+Mod)%Mod,k-i,Mod)%Mod;
    	}
    	for(int i=1;i<=m;i++){
    		q[i]=(q[i-1]+g[i-1])%Mod;
    	}
    	f[0][m]=s[0][m]=1;
    	for(int i=1;i<=n;i++){
    		for(int j=1;j<=m;j++){
    			f[i][j]=1ll*g[m-j]*((1ll*(s[i-1][m]-s[i-1][m-j]+Mod)%Mod)*q[j]%Mod-h[i-1][j]+Mod)%Mod;
    			s[i][j]=(s[i][j-1]+f[i][j])%Mod;
    			h[i][j]=(h[i][j-1]+1ll*g[j-1]*s[i][j-1])%Mod;
    		}
    	}
    	printf("%d
    ",s[n][m]);
    	return 0;
    }
    
  • 相关阅读:
    【C++札记】友元
    【C++札记】const关键字
    【C++札记】实现C++的string类
    【C++札记】拷贝构造函数,浅拷贝和深拷贝
    【C++札记】内联函数
    【C++札记】函数重载
    文章博客导航
    【C++札记】标准输入与输出
    毕业季,学子们又把翟天临推上了热搜!
    【底层原理】高级开发必须懂的"字节对齐"
  • 原文地址:https://www.cnblogs.com/withhope/p/13611582.html
Copyright © 2011-2022 走看看