题目链接:卡牌游戏
n个人,m张卡牌上有m个数字。庄家随机一张卡牌,数字为X,第X位出局,随后第X位的下一位做庄家,问,每个人最后获胜的概率是多少?
约瑟夫环的变形问题,这里每次等概率的抽牌,数字是随机的,
dp[i][j]: 还剩i个人时,第j个人获胜的概率 。
dp[1][1]=1.0 最后剩下的那个人获胜
从游戏的结局向前推,剩i人时,枚举m张卡牌,计算出下一局他的位置(也就是剩i-1人时),累加。我们算的是第j个人获胜的概率,如果刚好抽到他自己出局,忽略。
抽到出局的位置temp:
1,temp=j ,忽略
2,temp < j 时,他下一局的位置 j-temp;累加 dp[i-1][j-temp]
3,temp > j 时,他下一局的位置 i-temp+j;累加 dp[i-1] [i-temp+j]
#include<bits/stdc++.h>
#define ll long long
#define db double
using namespace std;
const int maxx=100;
double dp[maxx][maxx];
int a[maxx];
int main()
{
int n,m;
scanf("%d%d",&n,&m);
for(int i=1; i<=m; i++)
scanf("%d",&a[i]);
dp[1][1]=1.0;
for(int i=2; i<=n; i++)
for(int j=1; j<=i; j++)
for(int k=1; k<=m; k++)
{
int temp=a[k]%i==0 ? i:a[k]%i;
if(temp>j)
dp[i][j]+=(dp[i-1][i-temp+j]/(double)m);
else if(temp<j)
dp[i][j]+=(dp[i-1][j-temp]/(double)m);
}
char ch='%';
for(int i=1;i<=n;i++)
printf("%.2lf%c ",dp[n][i]*100,ch);
return 0;
}