列表

详情


NC50777. 毕业生的序列游戏

描述

  对于三个给定的正整数k, PA, PB, 现在有一个序列构造算法: 在初始条件下,有一个空序列,之后每次你会在该序列的末尾添加一个字母'a'或'b',添加'a'的概率是PA/(PA+PB),添加'b'的概率是PB/(PA+PB)。当在该序列中有至少k个子序列为'ab'的时候,该构造算法结束。

    现在,你需要求出该算法所构造出来的序列中'ab'子序列的期望个数为多少。显然,该结果可以用P/Q来表示,其中P和Q互质,并且Q≠0,P和Q模数为1e9+7。你需要打印出(P/Q)mod(1e9+7)。

注意,子序列是可以不连续的。

输入描述

第一行包含三个整数k,PA,PB(1≤k≤1000,1≤PA,PB≤1000000)。

输出描述

输出一个整数

示例1

输入:

1 1 1

输出:

2

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++11(clang++ 3.9) 解法, 执行用时: 32ms, 内存消耗: 11740K, 提交时间: 2019-07-06 16:56:11

#include<bits/stdc++.h>
#define ll long long
#define clr(x,i) memset(x,i,sizeof(x))
using namespace std;
const ll mod=1e9+7;
ll k,a,b,fm,f[1005][2005];
ll qpow(ll x,ll k)
{
	ll ret=1;
	while(k){
		if(k&1) ret*=x,ret%=mod;
		x*=x; x%=mod; k>>=1;
	}
	return ret;
}
int main()
{
	cin>>k>>a>>b;
	fm=qpow(a+b,mod-2)%mod;
	
	ll ans=0,t=a*qpow(b,mod-2)%mod;
	f[1][0]=1;
	for(int i=1;i<=k;i++){
		for(int j=0;j<=k;j++){
			if(i+j>=k){
				ans=(ans+f[i][j]*((i+j+t)%mod)%mod)%mod;
			}
			else{
				f[i][i+j]+=(f[i][j]*b%mod*fm%mod); f[i][i+j]%=mod;
				f[i+1][j]+=(f[i][j]*a%mod*fm%mod); f[i+1][j]%=mod;
			}
		}
	}
	cout<<ans<<endl;
	return 0;
}

C++14(g++5.4) 解法, 执行用时: 23ms, 内存消耗: 7912K, 提交时间: 2020-03-02 12:19:35

#include<bits/stdc++.h>
using namespace std;
const int mod=1e9+7;
long long k,pa,pb,invb,invab;
long long dp[1010][1010];
long long quick_pow(long long a,long long b)
{
	long long ans=1;
	while(b)
	{
		if(b&1)
			ans=ans*a%mod;
		a=a*a%mod;
		b>>=1;
	}
	return ans;
}
long long dfs(long long x,long long y)
{
	if(dp[x][y]!=0)
		return dp[x][y];
	if(x+y>=k)
		return dp[x][y]=(x+y+pa*invb%mod)%mod;
	return dp[x][y]=(pa*invab%mod*dfs(x+1,y)%mod+pb*invab%mod*dfs(x,x+y)%mod)%mod;
}
int main()
{
	cin>>k>>pa>>pb;
	invb=quick_pow(pb,mod-2);
	invab=quick_pow(pa+pb,mod-2);
	cout<<dfs(1,0)<<endl;
	return 0;
}

上一题