zoukankan      html  css  js  c++  java
  • loj6300 「CodePlus 2018 3 月赛」博弈论与概率统计

    link

    题意:

    A和B玩游戏,每轮A赢的概率为p。现在有T组询问,已知A赢了n轮输了m轮,没有平局,赢一局A得分+1,输一局得分-1,问A得分期望值?

    $n+m,Tleq 2.5 imes 10^5.$

    题解:

    首先p并没有用。我们需要的是计算所有可能局面A的得分和,最后除以$C_{n+m}^{n}$。

    发现得分不小于0非常奇怪,转化一下,考虑设最后一个为0的状态:A赢x次,输y次。那么得分为(n-x)-(m-y)=n-m+y-x。令k=y-x,则y=k+x。其中需要满足$kgeq max(m-n,0)$,原因:既要保证之前得分$leq 0$($ygeq x$),又要保证之后不会出现$leq 0$($m-yleq n-x$)。

    (x,y)抽象成平面上的点。整个游戏相当于一条从(0,0)到(n,m)的路径,A赢横坐标+1,A输纵坐标+1,它的得分应该是路径上y-x最大的点的y-x+n-m(最后一个0的状态肯定是在那里取到)。

    直接统计得分不那么容易。考虑对于某一个k计算经过直线y=x+k的路径条数$S_k$,那么它们的分数肯定$geq k+n-m$。$S_k-S_{k-1}$就是分数恰好为k+n-m的路径条数。如何计算$S_k$?将(0,0)到路径和y=x+k的第一个交点这部分沿y=x+k翻转,那么等价于计算(-k,k)到(n,m)的路径条数,方案数为$C_{n+m}^{n+k}$。

    假设$nge m$,那么可以列出这样一个式子:

    $$egin{equation}ans=sum_{k=0}^{m}(C_{n+m}^{n+k}-C_{n+m}^{n+k+1})(n-m+k)end{equation}$$

    一看就可以列项,化简以后得:

    $$egin{equation}ans=(n-m)C_{n+m}^{n}+sum_{k=0}^{m-1}C_{n+m}^{k}end{equation}$$

    $nleq m$同理,此时k从m-n开始,化简以后得:

    $$egin{equation}ans=sum_{k=0}^{n-1}C_{n+m}^kend{equation}$$

    于是我们只需处理$sum_{k=0}^{n}C_n^k$。设为$F(n,k)$,注意到$C_n^m=C_{n-1}^m+C_{n-1}^{m-1}$,所以$F(n+1,k)=2F(n,k)-C_n^k$;同时$F(n,k+1)=F(n,k)+C_n^{k+1}$。

    发现每次n±1/k±1的时候都可以快速维护F(n,k),可以莫队维护(或者分块预处理组合数)。

    并不是一定要长得像区间的东西才能用莫队维护。二维的且每次行列变化1后的结果能快速得到的量,也可以抽象成莫队问题。(听说莫队常数比分块来得小)

    复杂度$mathcal{O}(nsqrt{n})$。(理解了我半天)

    code:

    (bzoj卡常并不能过)

     1 #include<bits/stdc++.h>
     2 #define rep(i,x,y) for (int i=(x);i<=(y);i++)
     3 #define per(i,x,y) for (int i=(x);i>=(y);i--)
     4 #define ll long long
     5 #define inf 1000000001
     6 #define y1 y1___
     7 using namespace std;
     8 char gc(){
     9     static char buf[100000],*p1=buf,*p2=buf;
    10     return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
    11 }
    12 //#define gc getchar
    13 ll read(){
    14     char ch=gc();ll x=0;int op=1;
    15     for (;!isdigit(ch);ch=gc()) if (ch=='-') op=-1;
    16     for (;isdigit(ch);ch=gc()) x=(x<<1)+(x<<3)+ch-'0';
    17     return x*op;
    18 }
    19 #define N 250005
    20 #define mod 1000000007
    21 #define inv2 500000004
    22 int Q,fac[N],inv[N],ans[N];
    23 struct ask{int n,m,l,r,id,bl;}q[N];
    24 int ksm(int x,int p){
    25     int ret=1;
    26     for (;p;p>>=1,x=(ll)x*x%mod) if (p&1) ret=(ll)ret*x%mod;
    27     return ret;
    28 }
    29 void init(int n){
    30     fac[0]=1;
    31     rep (i,1,n) fac[i]=(ll)fac[i-1]*i%mod;
    32     inv[n]=ksm(fac[n],mod-2);
    33     per (i,n-1,0) inv[i]=(ll)inv[i+1]*(i+1)%mod;
    34 }
    35 bool cmp(ask x,ask y){return x.bl<y.bl||x.bl==y.bl&&x.r<y.r;}
    36 #define C(n,m) (n>=m?(ll)fac[n]*inv[m]%mod*inv[(n)-(m)]%mod:0)
    37 #define invC(n,m) ((ll)fac[m]*fac[(n)-(m)]%mod*inv[n]%mod)
    38 void upd(ll &x,int y){x+=y;x-=x>=mod?mod:0;}
    39 int main(){
    40     init(250000);
    41     Q=read();read();int blo=sqrt(Q);
    42     rep (i,1,Q){
    43         q[i].n=read(),q[i].m=read();
    44         q[i].id=i;
    45         q[i].l=q[i].n+q[i].m;q[i].r=min(q[i].n,q[i].m)-1;
    46         q[i].bl=(q[i].l-1)/blo+1;
    47     }
    48     sort(&q[1],&q[Q+1],cmp);
    49     int l=0,r=0;ll now=1;
    50     rep (i,1,Q){
    51         while (l>q[i].l) l--,upd(now,C(l,r)),now=(ll)now*inv2%mod;
    52         while (r<q[i].r) r++,upd(now,C(l,r));
    53         while (l<q[i].l) upd(now,now),upd(now,mod-C(l,r)),l++;
    54         while (r>q[i].r) upd(now,mod-C(l,r)),r--;
    55         ans[q[i].id]=(max(q[i].n-q[i].m,0)+now*invC(q[i].l,q[i].n))%mod;
    56     }
    57     rep (i,1,Q) printf("%d
    ",ans[i]);
    58     return 0;
    59 }
    View Code
  • 相关阅读:
    机器学习--强化学习
    机器学习--深度学习
    机器学习--维度灾难
    机器学习--最优化
    机器学习--降维
    机器学习--聚类
    机器学习--模型提升
    Git和gitHub用户名 邮箱
    Git线上操作
    版本控制器:Git
  • 原文地址:https://www.cnblogs.com/bestFy/p/9501399.html
Copyright © 2011-2022 走看看