gym 102059 C.Dstorv题解

89 篇文章 1 订阅

gym 102059 C.Dstorv题解

首先可以发现最终一定是一个分界点 i , ( i < n ) i,(i<n) i,(i<n)满足下标≤i的中留下 A A A个全部向左,其余的留下 B B B个全部向右。特殊的 i i i是那 A A A中的一个, i + 1 i+1 i+1是那 B B B中的一个。

我们可以想到 d p dp dp状态, f i , j f_{i,j} fi,j表示考虑第 i i i位,右边有 j j j个向左过来。

转移:
( a i = ′ H ′ ) (a_i='H') (ai=H) f i − 1 , j + 1 → f i , j f_{i-1,j+1}\rightarrow f_{i,j} fi1,j+1fi,j

( a i = ′ R ′ ) (a_i='R') (ai=R):

  1. f i , j − 1 ∗ h h + r → f i , j f_{i,j-1}*\large{\frac{h}{h+r}}\rightarrow f_{i,j} fi,j1h+rhfi,j,(向左的一个消失)
  2. f i − 1 , j ∗ r h + r → f i , j f_{i-1,j}*\large{\frac{r}{h+r}}\rightarrow f_{i,j} fi1,jh+rrfi,j

初始化: f 0 , A = 0 f_{0,A}=0 f0,A=0.

对于向右的一样处理。

时间复杂度 O ( n 2 ) O(n^2) O(n2)

Code:

/*
{By GWj
*/
#pragma GCC optimize(2)
#include<bits/stdc++.h>
#define rb(a,b,c) for(int a=b;a<=c;++a)
#define rl(a,b,c) for(int a=b;a>=c;--a)
#define LL long long
#define IT iterator
#define PB push_back
#define II(a,b) make_pair(a,b)
#define FIR first
#define SEC second
#define FREO freopen("check.out","w",stdout)
#define rep(a,b) for(int a=0;a<b;++a)
#define SRAND mt19937 rng(chrono::steady_clock::now().time_since_epoch().count())
#define random(a) rng()%a
#define ALL(a) a.begin(),a.end()
#define POB pop_back
#define ff fflush(stdout)
#define fastio ios::sync_with_stdio(false)
#define R(a) cin>>a
#define R2(a,b) cin>>a>>b
#define check_min(a,b) a=min(a,b)
#define check_max(a,b) a=max(a,b)
using namespace std;
const int INF=0x3f3f3f3f;
typedef pair<int,int> mp;
/*}
*/
const int MOD=1e9+7;
LL quick(LL A,LL B){
	if(B==0) return 1;
	LL  tmp=quick(A,B>>1);
	tmp*=tmp;
	tmp%=MOD;
	if(B&1)
		tmp*=A,tmp%=MOD;
 	return tmp;
}
LL inv(LL A) {return quick(A,MOD-2);}
LL l,r,h,R;
int n,A,B;
vector<vector<LL> > dp1,dp2;
vector<vector<LL> > work(string s){
	s='$'+s;
	vector<vector<LL > > dp=vector<vector<LL> > (5000+2,vector<LL>(5000+2,0.0));
	dp[0][A]=1.0;
	rb(i,1,n){
		rb(j,0,n){
			if(s[i]=='L'){
				dp[i][j]=dp[i-1][j+1];
			}
			else{
				if(!j) continue;
				dp[i][j]=dp[i-1][j]*r%MOD+dp[i][j-1]*l%MOD;
				if(dp[i][j]>=MOD) dp[i][j]-=MOD;
			}
		}
	}
	return dp;
}
int main(){
	fastio;
	cin>>n>>R>>h;
	l=(h)*inv(R+h)%MOD;
	r=(R)*inv(R+h)%MOD;
	string s;
	R(s);
	rep(i,n)
		if(s[i]=='H') s[i]='L';
	R2(B,A);
	dp1=work(s);
	swap(A,B);
	swap(l,r);
	reverse(ALL(s));
	rep(i,n)
	if(s[i]=='L') s[i]='R';
	else s[i]='L';
	dp2=work(s);
	LL rest=0;
	rb(i,0,n){
		int ii=n-i;
		rest+=dp1[i][0]*dp2[ii][0]%MOD;
		if(rest>=MOD) rest-=MOD;
	} 
	cout<<rest<<endl;
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值