求n+m局游戏恰好赢了n局的游戏的期望得分
记胜为+1,负为-1
期望得分可以用每种序列的得分*该种序列出现概率求和,最后再除以恰好出现n个1的概率
由此可以发现每种序列出现概率是相同的,就是说这个p并没有什么用
记
prei=∑ij=1ai
p
r
e
i
=
∑
j
=
1
i
a
i
一种序列的得分可以表示为
∑ai−min{prei}
∑
a
i
−
m
i
n
{
p
r
e
i
}
问题变成求最小前缀和的期望
这个期望又等于
∑−1i=−∞pi
∑
i
=
−
∞
−
1
p
i
,
pi
p
i
为最小前缀和<= i的概率
当n>=m时,这个pi=C(n+m,m+i)
用Catalan数的推导过程不难证明
n< m时候要特判一部分pi
问题变成了求一段组合数的前缀和
记
si,j=∑jk=0Cki
s
i
,
j
=
∑
k
=
0
j
C
i
k
有
si+1,j=si,j−Ci,j
s
i
+
1
,
j
=
s
i
,
j
−
C
i
,
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[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;
}