[CodePlus 2018 3 月赛] 博弈论与概率统计

Posted si-rui-yang

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[CodePlus 2018 3 月赛] 博弈论与概率统计相关的知识,希望对你有一定的参考价值。

link

题意简述

小 $A$ 与小 $B$ 在玩游戏,已知小 $A$ 赢 $n$ 局,小 $B$ 赢 $m$ 局,没有平局情况,且赢加一分,输减一分,而若只有 $0$ 分仍输不扣分。

已知小 $A$ 每次赢得概率为 $p$ ,问小 $A$ 得分期望。 $T$ 组数据。

$T,n,m\leq 2.5\times 10^5$

$solution:$

因为赢场输场已经固定,所以 $p$ 其实是没有用,则现在考虑计算小 $A$ 得分总和。

将赢输场前缀和,记为 $\s\$,则得分为 $n-m-min\s\$ 。假设所有 $-1$ 均有意义,则分数为 $n-m$ 。

设 $min\s\=x$,则第一次出现 $-1,-2,…,x$ 均无意义因为当时得分前为 $0$ 而又被 $-1$,无意义,共出现 $|x|$ 次情况,即得分为 $n-m-min\s\$。

所以现在的问题转化为给定 $n$ 个 $1$ 与 $m$ 个 $-1$ ,问最小前缀和为 $w$ 的方案数。

基本操作,将问题转化为平面移动问题。

若要求最小前缀和为 $w$ 的方案数,可以表示为从 $(0,0)$ 走到 $(n,m)$ 的方案数,每次往上或左走一步求经过 $y=x+w$ 但不能经过 $y=x+w+1$ 直线的方案数。

考虑求从 $(1,1)$ 到 $(n,m)$ 经过 $y=x+w$ 的方案数,可以将第一次经过 $y=x+w$ 的交点之前部分对 $y=x+w$ 对称,则 $(0,0)$ 对称到 $(-w,w)$ ,可以发现每次从 $(-w,w)$ 到 $(n,m)$ 经交点对称后对应一条合法路径,则其方案数为 $\dbinomn+mn+w$ 。

通过简单容斥原理得到若最小前缀和为 $w?$ 的方案数为 $\dbinomn+mn+w-\dbinomn+mn+w+1?$ 。

考虑赢 $n?$ 场输 $m?$ 场的得分,得分区间为 $[max\0,n-m\,n]?$ 。

分类讨论 $n,m$ 大小。

若 $n\geq m$ ,则得分区间在 $[n-m,n]$ , $min\s\\in [-m,0]$。

$$Ans=\sum_i=0^m (n-m+i) (\dbinomn+mn+i-\dbinomn+mn+i+1)\\=(n-m) \sum_i=0^m(\dbinomn+mn+i-\dbinomn+mn+i+1) +\sum_i=0^m i\times (\dbinomn+mm-i-\dbinomn+mm-i-1)\\=(n-m)\dbinomn+mn+\sum_i=0^m-1 \dbinomn+mi?$$

若 $n<m?$ ,则同理 $min\s\\in [-m,n-m]?$

$$Ans=\sum_i=m-n^m (n-m+i)\times\dbinomn+mm-i-\dbinomn+mm-i-1\\=(n-m)\dbinomn+mn+\sum_i=m-n^m i\times \dbinomn+mm-i-\sum_i=m-n^m-1 i\times \dbinomn+mm-i-1\\=(n-m)\dbinomn+mn+(m-n)\dbinomn+mn+\sum_i=m-n+1^m i\times \dbinomn+mm-i-\sum_i=m-n^m-1 i\times \dbinomn+mm-i-1=\sum_i=m-n+1^m-1 i\times\dbinomn+mm-i-\sum_i=m-n+1^m (i-1)\times \dbinomn+mm-i+1\\=\sum_i=m-n+1^m \dbinomn+mm-i\\=\sum_i=0^n-1\dbinomn+mi?$$

可以发现现在的问题为如何快速求 $F(n,k)=\sum_i=0^k \dbinomni$

可以发现 $F(n,k)=\sum_i=0^k \dbinomn-1i-1+\dbinomn-1i=F(n-1,k)-\dbinomn-1k$ 。即 $F(n,k)$ 与 $F(n-1,k)$ 和 $F(n-1,k)$ 都有递推关系。

直接将答案离线后莫队计算即可。

时间复杂度 $O((n+m)\sqrtn+m)$ 。

技术图片
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath> 
#define int long long
#define mod 1000000007
using namespace std;
inline int read()
    int f=1,ans=0;char c=getchar();
    while(c<0||c>9)if(c==-)f=-1;c=getchar();
    while(c>=0&&c<=9)ans=ans*10+c-0;c=getchar();
    return ans*f;

const int MAXN=500001;
struct Query
    int l,r,bl,id;
query[MAXN],tmp[MAXN];
bool cmp(Query x1,Query x2)
    if(x1.bl!=x2.bl) return x1.l<x2.l;
    if(x1.bl&1) return x1.r<x2.r;
    return x1.r>x2.r;

int T,p,Ans[MAXN],inv[MAXN],ifac[MAXN],fac[MAXN];
inline void init()
    fac[0]=1;for(int i=1;i<MAXN;++i) fac[i]=fac[i-1]*i,fac[i]%=mod;
    inv[1]=1;for(int i=2;i<MAXN;++i) inv[i]=(mod-mod/i)*inv[mod%i],inv[i]%=mod;
    ifac[0]=1;for(int i=1;i<MAXN;++i) ifac[i]=ifac[i-1]*inv[i],ifac[i]%=mod;
    return;

inline int C(int a,int b)if(a<b) return 0;return (((fac[a]*ifac[b])%mod)*ifac[a-b])%mod;
inline int F(int a,int b)return (((fac[b]*fac[a-b])%mod)*ifac[a])%mod;
inline int ksm(int a,int b)
    int ans=1;
    while(b)
        if(b&1) ans*=a,ans%=mod;
        a*=a,a%=mod;b>>=1;
    return ans;

int blo,bl[MAXN],l,r,ans,inv2;
int Mod(int x)return ((x%mod)+mod)%mod;
signed main()
//    freopen("20.in","r",stdin);
    init();
    T=read(),p=read();blo=501;
    for(register int i=0;i<MAXN;++i) bl[i]=(i-1)/blo+1;
    for(register int i=1;i<=T;++i)
        int n=read(),m=read();
        if(n>=m) Ans[i]=(n-m)*C(n+m,n),query[i].l=n+m,query[i].r=m-1,query[i].bl=bl[query[i].l];
        else query[i].l=n+m,query[i].r=n-1,query[i].bl=bl[query[i].l];
        query[i].id=i;
        tmp[i].l=n,tmp[i].r=m;
    sort(query+1,query+T+1,cmp);
    l=0,r=0,ans=1;inv2=ksm(2,mod-2);
    for(register int i=1;i<=T;++i)
        while(l<query[i].l) ans=Mod(2*ans-C(l,r)),l++;
        while(l>query[i].l) ans=Mod(Mod(ans+C(l-1,r))*inv2),l--;
        while(r<query[i].r) ans+=C(l,r+1),ans=Mod(ans),r++;
        while(r>query[i].r) ans-=C(l,r),ans=Mod(ans),r--;
        Ans[query[i].id]+=ans,Ans[query[i].id]%=mod;
    
    for(register int i=1;i<=T;++i)Ans[i]*=F(tmp[i].l+tmp[i].r,tmp[i].l);Ans[i]%=mod;
    for(register int i=1;i<=T;++i) printf("%lld\n",Ans[i]);
    return 0;
View Code

 

以上是关于[CodePlus 2018 3 月赛] 博弈论与概率统计的主要内容,如果未能解决你的问题,请参考以下文章

@loj - 6354@「CodePlus 2018 4 月赛」最短路

「CodePlus 2017 12 月赛」白金元首与独舞

LibreOJ#6259. 「CodePlus 2017 12 月赛」白金元首与独舞

走进矩阵树定理--「CodePlus 2017 12 月赛」白金元首与独舞

[CodePlus 2017 11月赛&洛谷P4058]木材 题解(二分答案)

[LOJ 6249]「CodePlus 2017 11 月赛」汀博尔