1. 程式人生 > >Codeforces 908D New Year and Arbitrary Arrangement(概率DP,邊界條件處理)

Codeforces 908D New Year and Arbitrary Arrangement(概率DP,邊界條件處理)

sin color 一個 pan ++ urn fin [1] bsp

題目鏈接 Goodbye 2017 Problem D

題意 一個字符串開始,每次有$\frac{pa}{pa+pb}$的概率在後面加一個a,$\frac{pb}{pa+pb}$的概率在後面加一個$b$。

   求當整個串中有至少$k$個$ab$的時候(不需要連續,下同),字符串中$ab$個數的期望。

設$f[i][j]$為字符串有$i$個$a$,$j$個$ab$的時候字符串中$ab$個數的期望

設$p = \frac{pa}{pa+pb}$, $q = \frac{pb}{pa+pb}$

那麽對於正常的情況(非邊界情況),

$f[i][j] = f[i+1][j] * p + f[i + 1][i + j] * q$

對於邊界情況,即當$i + j >= k$且$j < k$的時候,這個時候再加一個$a$就滿足了題意的條件。

這個情況下$f[i][j] - i - j$應該都是一樣的。令$f[i][j] - i - j = c$。

$c = pq + 2p^{2}q + 3p^{3}q + ... + ...$

時間復雜度$O(n^{2})$

#include <bits/stdc++.h>

using namespace std;

#define rep(i, a, b)	for (int i(a); i <= (b); ++i)
#define dec(i, a, b)	for (int i(a); i >= (b); --i)

const int N   = 1e3 + 10;
const int mod = 1e9 + 7;

int f[N][N];
int k, pa, pb, A, B, C;

void gcd(int a, int b, int &x, int &y){
	if (!b) {x = 1; y = 0;}
	else { gcd(b, a % b, y, x); y -= x * (a / b);}
}

int inv(int a){
        int x, y;
        gcd(a, mod, x, y);
        return (x % mod + mod) % mod;
}

int main(){

	scanf("%d%d%d", &k, &pa, &pb);
	A = 1ll * pa * inv(pa + pb) % mod;
	B = (1 - A + mod) % mod;
	C = 1ll * pa * inv(pb) % mod;
	dec(i, k, 1){
		dec(j, k, 0){	
			f[i][j] = i + j >= k ? (i + j + C) % mod: (1ll * A * f[i + 1][j] + 1ll * B * f[i][i + j]) % mod;
		}
	}

	printf("%d\n", f[1][0]);
	return 0;
}

  

Codeforces 908D New Year and Arbitrary Arrangement(概率DP,邊界條件處理)