记忆化搜索dp
#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define int long long
int mod = 1e9 + 7;
typedef long long ll;
int qmi(int a,int b,int p){ //快速幂
int res = 1;
while(b){
if(b&1) res= res*a%p;
b >>=1;
a = a*a%p;
}
return res;
}
void solve() {
int x;
int a1,b1,a2,b2;
cin>>x>>a1>>b1>>a2>>b2;
int p1 = a1 * qmi(b1,mod - 2,mod) % mod; //计算小红吃掉棋子的概率
int p2 = a2 * qmi(b2,mod - 2,mod) % mod; //计算小紫吃掉棋子的概率
/**
* 计算四种情况的概率
*/
int P1 = p1 * p2 % mod;
int P2 = p1 * (mod + 1 - p2) % mod;
int P3 = (mod + 1 - p1) * p2 % mod;
int P4 = (mod + 1 - p1) * (mod + 1 - p2) % mod;
//由方程推出需要计算P5
int P5 = (mod + 1 - P4) % mod;
int inv = qmi(P5,mod - 2,mod);
vector<vector<int>> dp(x+1,vector<int>(x+1,-1));
/**
* dfs,记忆化搜索,dfs(i,j)表示小红吃掉i个棋子,小紫吃掉j个棋子,小红获胜的概率
* dfs(i,j) = P1 * dfs(i+1,j+1) + P2 * dfs(i+1,j) + P3 * dfs(i,j+1) + P4 * dfs(i,j)
* 解方程移项得:dfs(i,j) = (P1 * dfs(i+1,j+1) + P2 * dfs(i+1,j) + P3 * dfs(i,j+1)) / (1 - P4 )
**/
auto dfs = [&](auto dfs,int c1,int c2) -> int {
//递归的出口
if(c1 == x){ //如果小红下满棋盖,就无法获胜
return dp[c1][c2] = 0;
}else if(c2 == x){ //如果小紫下满棋盖,就一定获胜
return dp[c1][c2] = 1;
}
/**
* 记忆化搜索,如果以及有了,就不用递归计算了
*/
if(dp[c1][c2] != -1){
return dp[c1][c2];
}
int A = P1 * dfs(dfs,c1 + 1,c2 + 1) % mod;
int B = P2 * dfs(dfs,c1 + 1,c2) % mod;
int C = P3 * dfs(dfs,c1,c2 + 1) % mod;
return dp[c1][c2] = (A + B + C) % mod * inv % mod;
};
cout<<dfs(dfs,0,0)<<endl; //入口,代表小红和小紫初始没放棋子的状态
}
signed main() {
ios::sync_with_stdio(0);
cin.tie(0);
int tt = 1;
// cin >> tt;
while (tt--) {
solve();
}
return 0;
}