New Year and Arbitrary Arrangement
链接:登录—专业IT笔试面试备考平台_牛客网
来源:牛客网
题目描述
给定三个整数 k,pa,pbk,p_a ,p_bk,pa,pb 以及一个空的序列。
每一次填充操作,会有 papa+pb\frac{p_a}{p_a+p_b}pa+pbpa的概率在序列末尾添加字符 'a'(不含引号),反之,有 pbpa+pb\frac{p_b}{p_a+p_b}pa+pbpb 的概率在序列末尾添加字符 'b' (不含引号)。填充操作会一直执行直到序列中出现至少 kkk 个形如 "ab" 的子序列。
求填充操作结束时形如 "ab" 的子序列的期望出现次数,并对 109+710^9+7109+7 取模。
输入描述:
第一行包含三个整数 k,pa,pb(1≤k≤1000,1≤pa,pb≤1000000)k,p_a,p_b(1\leq k\leq 1000,1\leq p_a,p_b\leq 1000000)k,pa,pb(1≤k≤1000,1≤pa,pb≤1000000)。
输出描述:
输出一个整数,代表取模后的期望次数。
示例1
输入
复制1 1 1
1 1 1
输出
复制2
2
说明
第一个样例中,我们会不断添加字符知道子序列 "ab" 至少出现了一次。例如,我们有 1/4 的概率得到序列 "ab",有 1/16 的概率得到序列 "bbab",以及由 1/8 的概率得到序列 "aab"。注意,我们不可能得到序列 "aabab" ,因为当我们得到前缀 "aab" 时就会立即停止操作。
所有合法序列中,子序列 "ab" 的期望出现次数是 2。
示例2
输入
3 1 4
输出
370000006
说明
第二个样例中,未取模的答案是 341100\frac{341}{100}100341。
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define endl '\n'
const ll mod = 1e9 + 7;
const int N = 1001;
int x, y;
void exgcd(int a, int b, int &x, int &y)
{
if (b == 0)
{
x = 1;
y = 0;
return;
}
exgcd(b, a % b, x, y);
int t = x;
x = y;
y = t - a / b * y;
return;
}//用扩展欧几里得求逆元
ll inv(int a, int b)
{
exgcd(a, b, x, y);
return (x % b + b) % b;
}
ll k, a, b, pab, pa, pb;
ll dp[N][N];
int main()
{
cin >> k >> a >> b;
pab = a + b;
pa = a * inv(pab, mod) % mod;
pb = b * inv(pab, mod) % mod;
for (int i = k - 1; i >= 0; i--)
{
for (int j = k; j >= 1; j--)
{
if (i + j >= k)
{
dp[i][j] = ((i + j) % mod + pa * inv(pb, mod) % mod) % mod;
}
else
{
dp[i][j] = (pb*dp[i+j][j]%mod + pa*dp[i][j+1]%mod)%mod;
}
}
}
dp[0][0]=dp[0][1]%mod;
cout<<dp[0][0];
}