Good Bye 2017 D. New Year and Arbitrary Arrangement[dp II][概率论][数论]

题目:http://codeforces.com/contest/908/problem/D

题意:每次有$\frac{pa}{pa+pb}$的概率选择‘a’,有$\frac{pb}{pa+pb}$的概率选择‘b’,每当串中出现k个ab(不一定连续)时停止操作,输出期望。

分析:乱七八糟的东西用逆元处理一下,dp中必然包含出现的ab个数,但是无法转移,所以再存一维作为a的个数。

dp[i][j]代表前面有i个a,有j个ab的情况数。转移的状态非常好想,下一个是a就转移到dp[i+1][j],如果是b就转移到dp[i][i+j],因为前缀的b并不会产生任何贡献,所以令dp[1][0]=1作为初状态(因为第一个如果是b相当于没有,所以抽到a的概率为100%)。

另一个问题就是截止点,题目要求超过k个ab就截止,那么当i+j>=k时抽到b截止,期望为i+j。但是还有情况就是一直抽到a,一直无法结束,这时候算他的基础期望为i+j,有pa的概率抽到a继续,则在下一个状态抽到b时贡献加1。意思就是说,有pa的概率加1,$pa^{2}$的概率加1,一直延伸到无限,用一个等比数列求和公式求n为无穷大时的值,算出后续的贡献为$\frac{pa}{1-pa}$。

所以当i+j>=k时对答案的贡献为$dp[i][j]*(i+j+\frac{pa}{1-pa})$。

代码:

 1 #define _CRT_SECURE_NO_DEPRECATE
 2 #pragma comment(linker, "/STACK:102400000,102400000")
 3 #pragma GCC optimize("Ofast")
 4 #pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
 5 #include<iostream>  
 6 #include<cstdio>  
 7 #include<fstream>  
 8 #include<iomanip>
 9 #include<algorithm>  
10 #include<cmath>  
11 #include<deque>  
12 #include<vector>
13 #include<bitset>
14 #include<queue>  
15 #include<string>  
16 #include<cstring>  
17 #include<map>  
18 #include<stack>  
19 #include<set>
20 #include<functional>
21 #define pii pair<ll,ll>
22 #define mod 1000000007
23 #define mp make_pair
24 #define pi acos(-1)
25 #define eps 0.00000001
26 #define mst(a,i) memset(a,i,sizeof(a))
27 #define all(n) n.begin(),n.end()
28 #define lson(x) ((x<<1))  
29 #define rson(x) ((x<<1)|1) 
30 #define inf 0x3f3f3f3f
31 typedef long long ll;
32 typedef unsigned long long ull;
33 using namespace std;
34 
35 ll extendGcd(ll a, ll b, ll &x, ll &y) {
36     ll ans, t;
37     if (b == 0) {
38         x = 1; y = 0;
39         return a;
40     }
41     ans = extendGcd(b, a%b, x, y);
42     t = x; x = y; y = t - (a / b)*y;
43     return ans;
44 }
45 
46 ll getInv(ll a, ll m = mod) {
47     ll x, y, d;
48     d = extendGcd(a, m, x, y);
49     if (d == 1)
50         return (x%m + m) % m;
51     else
52         return -1;
53 }
54 const int maxn = 1e3 + 5;
55 ll dp[maxn][maxn];
56 int n;
57 
58 int main()
59 {
60     ios::sync_with_stdio(false);
61     cin.tie(0); cout.tie(0);
62     int i, j, k, m;
63     int pa, pb;
64     cin >> n >> pa >> pb;
65     ll ans = 0;
66     ll sm = getInv(pa + pb);
67     pa = (pa*sm) % mod;
68     pb = (pb*sm) % mod;
69     dp[1][0] = 1;
70     ll qu = (1 - pa + mod) % mod;
71     qu = (getInv(qu)*pa) % mod;
72     for (ll i = 1; i <= n; ++i)
73         for (ll j = 0; j <= n; ++j)
74             if (i + j >= n)
75                 ans = (ans + dp[i][j] * (i + j + qu)) % mod;
76             else
77             {
78                 dp[i + 1][j] = (dp[i + 1][j] + dp[i][j] * pa) % mod;
79                 dp[i][i + j] = (dp[i][i + j] + dp[i][j] * pb) % mod;
80             }
81     cout << ans << endl;
82     return 0;
83 }

 

posted @ 2017-12-31 11:54  Meternal  阅读(397)  评论(0编辑  收藏  举报