2025 ICPC Nanchang Invitational and Jiangxi Provincial Collegiate Programming Contest——C

简化题意

一副除去大小王的扑克牌,初始两人各拿五张,你知道自己的牌,可以换 掉其中的若干张牌并加注同等数量的筹码,最终总点数大的一方胜并赢得 全部筹码,问最大收益的期望。

补题点这里

问题转化为 47 47 47 张牌 ,抽 k k k 张换掉最小的 k k k 张,对方抽 5 5 5 张,获胜的期望,终止状态肯定是我抽 k k k 张牌,对方抽 5 5 5 张牌,定义 f [ i ] [ x ] [ j ] [ y ] f[i][x][j][y] f[i][x][j][y] 表示我抽了 i i i 张牌,得分是 x x x,对方抽了 j j j 张牌,得分为 y y y 的方案数,那么总方案数就是
T k = ∑ x ∈ [ 0 , 65 ] ∑ y ∈ [ 0 , 65 ] f [ k ] [ x ] [ 5 ] [ y ] = ∑ x ∈ [ 0 , 65 ] , y ∈ [ 0 , 65 ] f [ k ] [ x ] [ 5 ] [ y ] T_k=\sum_{x\in[0,65]}\sum_{y\in[0,65]} f[k][x][5][y]\\=\sum_{x\in[0,65],y\in[0,65]} f[k][x][5][y] Tk=x[0,65]y[0,65]f[k][x][5][y]=x[0,65],y[0,65]f[k][x][5][y]
下面省略 x x x , y y y 的范围

那么我恰好得分为 x x x ,对手恰好得分为 y y y 的概率是
P    =    f k , x , 5 , y T k . P \;=\; \frac{f_{k,x,5,y}}{T_k}. P=Tkfk,x,5,y.
S k : = S_k:= Sk:= 剩下的 5 − k 5-k 5k 张最大牌得分之和

如果 S k + x > y S_k+x>y Sk+x>y ,我赢,收益为 k k k

如果 S k + x < y S_k+x<y Sk+x<y ,我输,收益为 − k -k k

针对所有 ( x , y ) (x,y) (x,y) 的期望,我们先把收益与概率相乘,再求和相加,故期望为
E k = ∑   S k + x > y   ( + k )   f k , x , 5 , y T k ⏟ 赢的期望贡献    +    ∑   S k + x < y   ( − k )   f k , x , 5 , y T k ⏟ 输的期望贡献 . E_k = \underbrace{ \sum_{\,S_k+x>y\,} (+k)\,\frac{f_{k,x,5,y}}{T_k} }_{\text{赢的期望贡献}} \;+\; \underbrace{ \sum_{\,S_k+x<y\,} (-k)\,\frac{f_{k,x,5,y}}{T_k} }_{\text{输的期望贡献}}. Ek=赢的期望贡献 Sk+x>y(+k)Tkfk,x,5,y+输的期望贡献 Sk+x<y(k)Tkfk,x,5,y.

由于 k k k T k T_k Tk 都和 ( x , y ) (x,y) (x,y) 无关,可提出到求和符号外,故
E k = ∑ s k + x > y f k , x , 5 , y ∑ x , y f k , x , 5 , y    k    +    ∑ s k + x < y f k , x , 5 , y ∑ x , y f k , x , 5 , y    ( − k ) . E_k= \frac{ \sum_{s_k+x>y} f_{k,x,5,y} }{ \sum_{x,y}f_{k,x,5,y} }\;k \;+\; \frac{ \sum_{s_k+x<y} f_{k,x,5,y} }{ \sum_{x,y}f_{k,x,5,y} }\;(-k). Ek=x,yfk,x,5,ysk+x>yfk,x,5,yk+x,yfk,x,5,ysk+x<yfk,x,5,y(k).

现在考虑如何求DP数组,开成这样的DP数组,需要积累的是一般都需要原地更新,意味着正向递推会重复计算,所以每一维都需要倒序计算,或者写一个副本,每次DP完swap

#pragma GCC optimize(3,"Ofast","inline")
#include<bits/stdc++.h>
using namespace std;
using i64 = long long;
using i128 = __int128;

constexpr int mod = 998244353;
i64 qp(i64 a,i64 b){
    i64 ans = 1;
    while(b){
        if(b&1) ans = ans*a%mod;
        a = a*a%mod;
        b>>=1;
    }
    return ans;
}
i64 f[6][66][6][66];//J抽了i张点数是x的方案D抽了j张点数是y的方案数
int norm(string &s){
    if(s=="A") return 1;
    if(s=="10") return 10;
    if(s=="J") return 11;
    if(s=="Q") return 12;
    if(s=="K") return 13;
    return s[0]-'0';
}
int cnt[15];
signed main(){
    ios::sync_with_stdio(0);cin.tie(0);
    f[0][0][0][0]=1;
    vector<int> my(5);
    for(int i = 0;i<5;++i){
        string c;
        cin>>c;
        cnt[norm(c)]++;
        my[i] = norm(c);
    }
    vector<int> a;
    for(int i = 1;i<=13;++i){
        for(int j = 1;j<=4-cnt[i];++j){
            a.emplace_back(i);
        }
    }
    //所有都需要倒序枚举
    for(auto &z:a){
        for(int i = 5; i >= 0; --i){
            for(int x = 65; x >= 0; --x){
                for(int j = 5; j >= 0; --j){
                    for(int y = 65; y >= 0; --y){
                        // 1) 不要这张牌:什么都不做,f[i][x][j][y] 保持
                        // 2) 给我补牌
                        if(i+1 <= 5 && x+z <= 65){
                          f[i+1][x+z][j][y] = (f[i+1][x+z][j][y] + f[i][x][j][y]) % mod;
                        }
                        // 3) 给对手补牌
                        if(j+1 <= 5 && y+z <= 65){
                          f[i][x][j+1][y+z] = (f[i][x][j+1][y+z] + f[i][x][j][y]) % mod;
                        }
                    }
                }
            }
        }
    }
    sort(my.begin(),my.end(),greater());
    for(int k = 1;k<=5;++k){//换掉k张
        i64 ans = 0;
        i64 sk =0;
        for(int i = 0;i<5-k;++i) sk+=my[i];
        i64 frac =0,f1=0,f2=0;
        for(int x = 0;x<=65;++x){
            for(int y = 0;y<=65;++y){
                (frac+=f[k][x][5][y])%=mod;
                if(sk+x>y) (f1+=f[k][x][5][y])%=mod;
                if(sk+x<y) (f2+=f[k][x][5][y])%=mod;
            }
        }
        frac = qp(frac,mod-2);
        ans = (k*f1%mod*frac%mod-k*f2%mod*frac%mod+mod)%mod;
        cout<<ans<<"\n";
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值