比赛总结
题目
题意:
两个人玩扑克牌,A每局输赢的概率都是0.5.如果A有a张,B有b张,c=min(a,b),则该局获胜的人可从输的一方得到c张牌。谁先失去所有牌就输掉游戏。给出初始局面,求游戏进行的轮数的期望和A获胜的概率。
题解:
初看是概率DP,但是因为是个图所以不好写,然后又用高斯消元,但是某些局面某些矩阵元素会超过long long。测了几个自己的样例,发现获胜的概率就是a/(a+b),而进行的轮数直接搜索就可以:一个局面(a!=b)只有两个子局面,立刻结束或者继续,因为概率都是0.5,所以每搜一层就乘0.5,搜到25层以后已经对答案没什么影响了,可以直接忽略。
a、b的和为奇数时可以直接输出2。
//Time: //Length: #include <cstdio> #include <cstdlib> #include <cstring> #include <algorithm> #include <queue> using namespace std; #define MAXN 310 #define MP(x,y) make_pair(x,y) #define FI first #define SE second int a,b; int gcd(int a,int b) { while(a%b!=0) a%=b,swap(a,b); return b; } double dfs(int a,int b,int dep) { if(dep>25) return 0; if(a==0||b==0) return 0; int t=min(a,b); return (dfs(a-t,b+t,dep+1)+dfs(a+t,b-t,dep+1))*0.5+1; } int main() { //freopen("/home/moor/Code/input","r",stdin); int ncase,t; scanf("%d",&ncase); for(int hh=1;hh<=ncase;++hh) { scanf("%d%d",&a,&b); t=gcd(a,b); a/=t,b/=t; printf("Case %d: ",hh); printf("%.6f %.6f\n",(a+b)&1?2:dfs(a,b,1),a*1.0/(a+b)); } return 0; }