CF908D New Year and Arbitrary Arrangement

本文解析了CodeForces上的一道题目NewYearandArbitraryArrangement,通过动态规划求解给定条件下序列中‘ab’子序列出现次数的期望值。文章详细介绍了算法思路,并给出了解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

原题链接:http://codeforces.com/problemset/problem/908/D

New Year and Arbitrary Arrangement

You are given three integers k, pa and pb.

You will construct a sequence with the following algorithm: Initially, start with the empty sequence. Each second, you do the following. With probability pa / (pa + pb), add ‘a’ to the end of the sequence. Otherwise (with probability pb / (pa + pb)), add ‘b’ to the end of the sequence.

You stop once there are at least k subsequences that form ‘ab’. Determine the expected number of times ‘ab’ is a subsequence in the resulting sequence. It can be shown that this can be represented by P / Q, where P and Q are coprime integers, and . Print the value of .

Input

The first line will contain three integers integer k, pa, pb (1 ≤ k ≤ 1 000, 1 ≤ pa, pb ≤ 1 000 000).

Output

Print a single integer, the answer to the problem.

Examples
input

1 1 1

output

2

input

3 1 4

output

370000006

Note

The first sample, we will keep appending to our sequence until we get the subsequence ‘ab’ at least once. For instance, we get the sequence ‘ab’ with probability 1/4, ‘bbab’ with probability 1/16, and ‘aab’ with probability 1/8. Note, it’s impossible for us to end with a sequence like ‘aabab’, since we would have stopped our algorithm once we had the prefix ‘aab’.

The expected amount of times that ‘ab’ will occur across all valid sequences is 2.

For the second sample, the answer is equal to 341100 341 100 .

题目大意

起始为一个空序列, papa+pb p a p a + p b 的概率在后面加一个 a a pbpa+pb的概率在后面加一个 b b ,问有k个子序列 ab a b 时的期望长度为多少。

题解

先想一个简单的 dp d p

dp[i][j] d p [ i ] [ j ] 表示该序列前缀为 i i a,有 j j 个子序列ab时的期望长度,有转移方程如下:

dp[i][j]=dp[i+1][j]papa+pb+dp[i][j+i]pbpa+pb d p [ i ] [ j ] = d p [ i + 1 ] [ j ] p a p a + p b + d p [ i ] [ j + i ] p b p a + p b

比较好理解,分别表示在序列后面加上 a,b a , b 的情况。

但是,这个转移 naive n a i v e 了,当究极非酋的时候,就会出现 ababbaaaaa... a b a b b a a a a a . . . 这样的无穷多 a a 就是不出现b的情况,这样我们就会无限 dp d p 下去。。。

上述情况中, i+j i + j 已经大于 k k 了,只要再出现一个b,就能满足要求,但 b b 就是不出来,所以我们需要手算这个情况:

dp[i][j]=(i+j)pb+(i+j+1)papb+(i+j+2)pa2pb+...dp[i][j]pa=(i+j)papb+(i+j+1)pa2pb+(i+j+2)pa3pb+...(1pa)dp[i][j]=(i+j)pb+pb(pa+pa2+pa3+...)dp[i][j]pb=(i+j)pb+pbpa(1pb)pbdp[i][j]=i+j+pa(1pb)pbdp[i][j]i+j+papb

只需要把 i+j>k i + j > k 时的 dp d p 值赋值为 i+j+papb i + j + p a p b 即可。

代码
#include<bits/stdc++.h>
using namespace std;
const int M=1005,mod=1e9+7;
int dp[M][M],k,pa,pb;
void in(){scanf("%d%d%d",&k,&pa,&pb);}
void exgcd(int a,int b,int &x,int &y){b?(exgcd(b,a%b,y,x),y-=a/b*x):(x=1,y=0);}
int inv(int a){int x,y;return exgcd(a,mod,x,y),(x+mod)%mod;}
int dfs(int a,int ab)
{
    if(dp[a][ab]!=-1)return dp[a][ab];
    if(a+ab>=k)return (a+ab+1ll*pa*inv(pb))%mod;
    return dp[a][ab]=(1ll*((1ll*dfs(a+1,ab)*pa)%mod+(1ll*dfs(a,ab+a)*pb)%mod)%mod*inv(pa+pb))%mod;
}
void ac(){memset(dp,-1,sizeof(dp));printf("%d",dfs(1,0));}
int main(){in();ac();}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ShadyPi

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值