Live2D

CF98E Help Shrek and Donkey

link

Solution#

bunnny 之前搬的题,但是没有做🥵🥵🥵

我们不妨设 f(n,m) 表示先手有 n 张对手未知牌,后手有 m 张对手未知牌时先手获胜的概率。我们不妨先来观察一下双方的操作,先手可以查询自己没有的牌,也可以查询自己有的牌来达到欺骗的效果,后手就会有相信先手没有此牌或是觉得先手在欺骗自己的两种选择,不妨理解为“相信”和“不相信”。

我们首先考虑先手如果不欺骗,那么有 mm+1 的概率询问到后手手上的牌,1m+1 的概率询问到桌上的牌。如果询问到后手手上的牌,那么后手会拿出来他的牌,那么先手获胜的概率即为:mm+1(1f(m1,n)),如果询问到桌上的牌,那么后手如果相信了,则先手必输,否则先手必胜,先手获胜概率为 1m+1。再考虑先手进行欺骗,查询自己的牌,如果后手相信了,那么显然先手就必胜了,否则就相当于知道了先手的一张牌,先手获胜概率即为:1f(m,n1)。需要注意的是,当先手进行询问时,当询问到后手所拥有的牌,后手也可以选择不相信,但会把这张牌放出去,从而先手产生 mm+1(1f(m1,n)) 的收益。这里感觉比较抽象,但是可以理解为,无论怎么样,只要先手询问到了后手手上的牌就会产生这样的贡献,与后手是否相信无关。

把上述情况列为表格,我们可以得到:

后手\先手 询问 欺骗
相信 mm+1(1f(m1,n)) 1
不相信 1m+1+mm+1(1f(m1,n)) 1f(m,n1)

为了方便,把上列的概率分别成为 w1,1,w1,2,w2,1,w2,2

我们考虑先手假设以 p 的概率询问,以 1p 的概率进行欺骗,可以发现先手获胜的概率就是:

min(pw1,1+(1p)w1,2,pw2,1+(1p)w2,2)

先手就需要最大化该值。可以看出,这个可以表示为两个斜率正负性相反的直线求 min ,那么在交点处最为优秀。我们也可以从纳什均衡的角度出发,对于先手来说,无论后手如何选择收益都相同。

然后随便算一下就好了,复杂度 O(n2)

Code#

Copy
#include <bits/stdc++.h> using namespace std; #define Int register int #define MAXN 1005 //char buf[1<<21],*p1=buf,*p2=buf; //#define getchar() (p1==p2 && (p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++) template <typename T> inline void read (T &t){t = 0;char c = getchar();int f = 1;while (c < '0' || c > '9'){if (c == '-') f = -f;c = getchar();}while (c >= '0' && c <= '9'){t = (t << 3) + (t << 1) + c - '0';c = getchar();} t *= f;} template <typename T,typename ... Args> inline void read (T &t,Args&... args){read (t);read (args...);} template <typename T> inline void write (T x){if (x < 0){x = -x;putchar ('-');}if (x > 9) write (x / 10);putchar (x % 10 + '0');} template <typename T> inline void chkmax (T &a,T b){a = max (a,b);} template <typename T> inline void chkmin (T &a,T b){a = min (a,b);} int n,m; double f[MAXN][MAXN]; double dp (int x,int y){ if (f[x][y]) return f[x][y]; if (!y) return f[x][y] = 1; if (!x) return f[x][y] = 1.0 / (y + 1); double w11 = y * 1.0 / (y + 1) * (1 - dp (y - 1,x)),w21 = 1, w12 = w11 + 1.0 / (y + 1),w22 = 1 - dp (y,x - 1); double p = (w21 - w22) / (w12 + w21 - w11 - w22); return f[x][y] = p * w11 + (1 - p) * w21; } signed main(){ read (n,m);double p = dp (n,m); printf ("%.9f %.9f\n",p,1 - p); return 0; }
posted @   Dark_Romance  阅读(37)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示
CONTENTS