关于,我们有公式
so
对本题而言,显然在全1时必胜,不是全1时肯定选策略1
那么记录1的个数sum1,2的个数sum2,显然当前的胜率与
和
有关
那么取递归函数win表示当前赢的概率,参数分别为1的个数和2的个数,根据递归关系计算即可(返回值为分子分母)
(记得存已计算的值,不然重复递归会TLE)
#include <iostream>
#include <cstdio>
using namespace std;
#define LL long long
const LL mod = 1e9 + 7;
pair<LL,LL> f[1001][1001];
LL qpow(LL x, LL y)
{
LL a = 1;
x %= mod;
while (y)
{
if (y&1) a = a * x % mod;
x = x * x % mod;
y >>= 1;
}
return a;
}
pair<LL, LL> win(LL sum1, LL sum2)
{
if (sum1 < 0)
return {0l, 1l};
if (sum2 == 0)
return {1l, 1l};
if (f[sum1][sum2].second != 0l)
return f[sum1][sum2];
//{sum1, (sum1 + sum2)%mod}, {sum2, (sum1 + sum2)%mod}
pair<LL, LL> p1 = win(sum1-1, sum2), p2 = win(sum1+1, sum2-1), p3, p4;
if (sum1 == 0)
p3 = {0l, 1l};
else
p3.first = (p1.second-p1.first + mod) * sum1 % mod, p3.second = p1.second * (sum1 + sum2)%mod;
p4.first = (p2.second-p2.first + mod) * sum2 % mod, p4.second = p2.second * (sum1 + sum2)%mod;
f[sum1][sum2] = {(p3.first*p4.second%mod + p3.second*p4.first%mod)%mod,
p3.second*p4.second%mod};
return f[sum1][sum2];
}
int main()
{
int n, a;
LL sum1=0, sum2=0;
cin >> n;
for (int i=0; i <n; i ++)
{
cin >> a;
if (a == 1)sum1++;
else sum2++;
f[i][0] = {1l, 1l};
for (int j=1; j <n; j ++)
f[i][j] = {0l, 0l};
}
f[0][0] = {0l, 1l};
pair<LL,LL> ret = win(sum1, sum2);
//cout << ret.first << " " << ret.second << endl;
LL ans = qpow(ret.second, mod-2) * ret.first % mod;
printf ("%lld\n", ans);
return 0;
}

京公网安备 11010502036488号