1. 程式人生 > >CodePlus3月月賽 博弈論與概率統計

CodePlus3月月賽 博弈論與概率統計

求n+m局遊戲恰好贏了n局的遊戲的期望得分
記勝為+1,負為-1
期望得分可以用每種序列的得分*該種序列出現概率求和,最後再除以恰好出現n個1的概率
由此可以發現每種序列出現概率是相同的,就是說這個p並沒有什麼用
prei=j=1iai
一種序列的得分可以表示為aimin{prei}
問題變成求最小字首和的期望
這個期望又等於 i=1pipi 為最小字首和<= i的概率
當n>=m時,這個pi=C(n+m,m+i)
用Catalan數的推導過程不難證明
n< m時候要特判一部分pi
問題變成了求一段組合數的字首和

si,j=k=0jCik
si+1,j=si,jCi,j
我們可以按照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[n]*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; }