CF 908D New Year and Arbitrary Arrangement——期望dp
题目:http://codeforces.com/contest/908/problem/D
注意是子序列。加一个a对ab个数无影响;加一个b使ab个数多出它前面的a那么多个。所以状态里记录有多少个a和ab。
当 i+j>=k 的时候,再加一个b就结束了。用式子算一下期望,发现一个等比数列;用等比数列的公式算一下,变成一个值减去一个无限小的值,所以就是那个值了。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define ll long long using namespace std; const int N=1005,mod=1e9+7; int n,A,B,tmp,C,dp[N][N]; bool vis[N][N]; int pw(int x,int k) { int ret=1;while(k){if(k&1)ret=(ll)ret*x%mod;x=(ll)x*x%mod;k>>=1;}return ret; } int dfs(int i,int j) { if(vis[i][j])return dp[i][j]; vis[i][j]=1; if(i+j>=n) return dp[i][j]=(i+j+C)%mod; dp[i][j]=((ll)A*dfs(i+1,j)+(ll)B*dfs(i,i+j))%mod; return dp[i][j]; } int main() { scanf("%d%d%d",&n,&A,&B); tmp=pw(A+B,mod-2); C=(ll)A*pw(B,mod-2)%mod; A=(ll)A*tmp%mod; B=(ll)B*tmp%mod; printf("%d\n",dfs(1,0)); return 0; }