您的位置:首页 > 其它

CodePlus3月月赛 博弈论与概率统计

2018-03-05 16:15 246 查看
求n+m局游戏恰好赢了n局的游戏的期望得分

记胜为+1,负为-1

期望得分可以用每种序列的得分*该种序列出现概率求和,最后再除以恰好出现n个1的概率

由此可以发现每种序列出现概率是相同的,就是说这个p并没有什么用

记 prei=∑ij=1ai prei=∑j=1iai

一种序列的得分可以表示为∑ai−min{prei}∑ai−min{prei}

问题变成求最小前缀和的期望

这个期望又等于 ∑−1i=−∞pi∑i=−∞−1pi,pipi 为最小前缀和<= i的概率

当n>=m时,这个pi=C(n+m,m+i)

用Catalan数的推导过程不难证明

n< m时候要特判一部分pi

问题变成了求一段组合数的前缀和

记si,j=∑jk=0Ckisi,j=∑k=0jCik

有si+1,j=si,j−Ci,jsi+1,j=si,j−Ci,j

我们可以按照n+m−−−−−√n+m分段打表弄

code:

#include<set>
#include<map>
#include<deque>
#include<queue>
#include<stack>
#include<cmath>
#include<ctime>
#include<bitset>
#include<string>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<climits>
#include<complex>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;

inline void read(int &x)
{
char c; while(!((c=getchar())>='0'&&c<='9'));
x=c-'0';
while((c=getchar())>='0'&&c<='9') (x*=10)+=c-'0';
}
const int maxk = 755;
const int maxS = 750;
const int maxn = 500005;
const int maxm = 250005;
const int mod = 1e9+7;

int pw(int x,int k)
{
int re=1;
for(;k;k>>=1,x=(ll)x*x%mod) if(k&1)
re=(ll)re*x%mod;
return re;
}
int inv(int x){return pw(x,mod-2);}

int s[maxn],invs[maxn];
void pre()
{
s[0]=1; for(int i=1;i<maxn;i++) s[i]=(ll)s[i-1]*i%mod;
invs[maxn-1]=inv(s[maxn-1]);
for(int i=maxn-2;i>=0;i--) invs[i]=(ll)invs[i+1]*(i+1)%mod;
}
int C(int n,int m){return (ll)s
*invs[m]%mod*invs[n-m]%mod;}

int L[maxk],f[maxk][maxm],tp;

int cal(int n,int m)
{
if(m<0) return 0;
int now=1;
while(L[now+1]<=n) now++;
int c=f[now][m];
for(int i=L[now];i<n;i++)
{
c=(c<<1)-(i>=m?C(i,m):0);
if(c>=mod) c-=mod;
if(c<0) c+=mod;
}
return c;
}
int solve(int n,int m)
{
if(n>=m) return cal(n+m,m-1);
else return ((ll)(m-n-1)*C(n+m,m)%mod+cal(n+m,n))%mod;
}
int n,m,P;

int main()
{
//freopen("tmp.in","r",stdin);
//freopen("tmp.out","w",stdout);

pre();
for(L[tp=1]=1;;L[++tp]=L[tp-1]+maxS)
{
if(L[tp]>maxn) break;
int i=L[tp]; f[tp][0]=1;
for(int j=1;j<maxm;j++)
{
int c=i<j?0:C(i,j);
f[tp][j]=(f[tp][j-1]+c)%mod;
}
}

int T;read(T),read(P);
while(T--)
{
read(n),read(m);
int ans=(ll)(n-m)*C(n+m,m)%mod;
ans=(ans+solve(n,m))%mod;
ans=(ll)ans*inv(C(n+m,m))%mod;
ans=(ans+mod)%mod;
printf("%d\n",ans);
}

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: