CF1810G The Maximum Prefix
分享一种理解起来可能更为简单的思路。
假设我们钦定了
形象地,我们称这个钦定的最大前缀和
初始化:
转移方程:
长度为
注意处理边界问题,具体见代码。
时间复杂度为
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod = 1e9 + 7;
int t,n,x,y,p[5009],f[5009][5009][2];
inline int read(){
int s = 0,w = 1;
char ch = getchar();
while (ch > '9' || ch < '0'){ if (ch == '-') w = -1; ch = getchar();}
while (ch <= '9' && ch >= '0') s = (s << 1) + (s << 3) + (ch ^ 48),ch = getchar();
return s * w;
}
inline void add(int &x,int y){x += y; if (x >= mod) x -= mod;}
int qp(int x,int y){
int a = 1,b = x;
while (y){
if (y & 1) a = (ll) a * b % mod;
b = (ll) b * b % mod,y >>= 1;
}
return a;
}
int main(){
t = read();
while (t --){
n = read();
for (int i = 1;i <= n;i += 1) x = read(),y = read(),p[i] = (ll) x * qp(y,mod - 2) % mod;
for (int i = 0;i <= n;i += 1) f[0][i][!i] = read();
for (int i = 1;i <= n;i += 1){
int ans = 0;
for (int j = 0;j <= n;j += 1){
f[i][j][0] = f[i][j][1] = 0;
for (int o = 0;o < 2;o += 1){
if (j < n) add(f[i][j][o | (!j)],(ll) f[i - 1][j + 1][o] * p[i] % mod);
if (j > 0) add(f[i][j][o | (!j)],(ll) f[i - 1][j - 1][o] * (mod + 1 - p[i]) % mod);
}
add(ans,f[i][j][1]);
}
printf("%d ",ans);
}
puts("");
}
return 0;
}