#莫队,排列组合,容斥原理,卡特兰数#洛谷 4260 [Code+#3] 博弈论与概率统计

题目传送门


分析

由于赢的场数是固定的,所以概率并没有用,要想得分足够高,那就应该先输后赢

设输的场次为 -1,赢的场次为 1,得分前缀和为 s,那么得分就是 nmmin{s}

如果将输视为向上移,将赢视为向右移,那么恰好得到某个最小前缀和为 k 的方案数

相当于恰好碰到 y=x+k 又不能碰到 y=x+k+1 的方案数,那么将 (0,0) 对称到 (k,k)

容斥一下就是 C(n+m,n+k)C(n+m,n+k+1) 乘上得分 nm+k

由于得分不能为负值,所以分 n>mnm 两类讨论

对于第一类情况,相当于求解 k=0m(nm+k)[C(n+m,n+k)C(n+m,n+k+1)]

将两项分开计算得到答案为 (nm)C(n+m,n)+k=0m1C(n+m,k)

对于第二类情况,相当于求解 k=mnm(nm+k)[C(n+m,n+k)C(n+m,n+k+1)]

将两项分开计算得到答案为 k=0n1C(n+m,k)

最后答案都除以 C(n+m,m) 就可以得到期望得分

f(n,m)=i=0mC(n,i),则 f(n,m)=f(n,m1)+C(n,m),f(n,m)=2f(n1,m)C(n1,m)

所以对于后面的和式可以根据 n,m 的增减计算,用莫队解决


代码

#include <cstdio>
#include <cctype>
#include <algorithm>
using namespace std;
const int mod=1000000007,N=250011;
struct rec{int n,m,rk;}q[N];
int pos[N],fac[N],inv[N],ans[N],Q;
int iut(){
    int ans=0,f=1; char c=getchar();
    while (!isdigit(c)) f=(c=='-')?-f:f,c=getchar();
    while (isdigit(c)) ans=ans*10+c-48,c=getchar();
    return ans*f;
}
void print(int ans){
    if (ans>9) print(ans/10);
    putchar(ans%10+48);
}
bool cmp(rec x,rec y){
    if (pos[x.n]!=pos[y.n]) return pos[x.n]<pos[y.n];
    return (pos[x.n]&1)?(x.m<y.m):(x.m>y.m);
}
void Mo(int &x,int y){x=x+y>=mod?x+y-mod:x+y;}
int C(int n,int m){
    if (n<m) return 0;
    return 1ll*fac[n]*inv[m]%mod*inv[n-m]%mod;
}
int main(){
    fac[0]=fac[1]=inv[0]=inv[1]=1;
    for (int i=2;i<N;++i) inv[i]=1ll*(mod-mod/i)*inv[mod%i]%mod,pos[i]=i/500;
    for (int i=2;i<N;++i) fac[i]=1ll*fac[i-1]*i%mod,inv[i]=1ll*inv[i-1]*inv[i]%mod;
    Q=iut(),iut();
    for (int i=1;i<=Q;++i){
        int n=iut(),m=iut();
        if (n>m) ans[i]=n-m,q[i]=(rec){n+m,m-1,i};
            else q[i]=(rec){n+m,n-1,i};
    }
    sort(q+1,q+1+Q,cmp);
    int n=0,m=0,now=1;
    for (int i=1;i<=Q;++i){
    	int t=1ll*inv[q[i].n]*fac[q[i].m+1]%mod*fac[q[i].n-q[i].m-1]%mod;
        while (n>q[i].n) Mo(now,C(--n,m)),now=500000004ll*now%mod;
        while (n<q[i].n) Mo(now,now),Mo(now,mod-C(n++,m));
        while (m<q[i].m) Mo(now,C(n,++m));
        while (m>q[i].m) Mo(now,mod-C(n,m--));
        Mo(ans[q[i].rk],1ll*now*t%mod);
    }
    for (int i=1;i<=Q;++i) print(ans[i]),putchar(10);
    return 0;
}
posted @   lemondinosaur  阅读(18)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 张高兴的大模型开发实战:(一)使用 Selenium 进行网页爬虫
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
点击右上角即可分享
微信分享提示