【Luogu】P2059卡牌游戏(概率DP)
这绝壁是道紫难度的题
请移步xyz32678的题解。
设f[i][j]是有i个人参加了游戏,1是庄家,最后j胜出的概率。
我们可以发现,这个游戏影响胜出的概率的只有庄家的相对位置和人数,跟玩家的具体编号是无关的。 于是我们可以枚举D,表示庄家目前抽到的牌值为D。
则有if(d>j) f[i][j]+=f[i-1][i-d+1]/m
if(d<j) f[i][j]+=f[i-1][j-d]/m
这样子。最后f[n][i]就是玩家胜出的概率。
发现写题解的过程有助于理解题解……
代码放上。
#include<cstdio> #include<cstdlib> #include<cstring> #include<cctype> inline long long read(){ long long num=0,f=1; char ch=getchar(); while(!isdigit(ch)){ if(ch=='-') f=-1; ch=getchar(); } while(isdigit(ch)){ num=num*10+ch-'0'; ch=getchar(); } return num*f; } double f[100][100]; int q[1000]; int main(){ int n=read(),m=read(); for(int i=1;i<=m;++i) q[i]=read(); f[1][1]=1; for(int i=2;i<=n;++i) for(int j=1;j<=i;++j) for(int k=1;k<=m;++k){ int d=q[k]%i; if(d==0) d=i; if(d>j) f[i][j]+=f[i-1][i-d+j]/m; if(d<j) f[i][j]+=f[i-1][j-d]/m; } for(int i=1;i<=n;++i) printf("%.2lf%% ",f[n][i]*100); return 0; }
xyz32768 爆强
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cctype>
inline long long read(){
long long num=0,f=1;
char ch=getchar();
while(!isdigit(ch)){
if(ch=='-') f=-1;
ch=getchar();
}
while(isdigit(ch)){
num=num*10+ch-'0';
ch=getchar();
}
return num*f;
}
double f[100][100];
int q[1000];
int main(){
int n=read(),m=read();
for(int i=1;i<=m;++i) q[i]=read();
f[1][1]=1;
for(int i=2;i<=n;++i)
for(int j=1;j<=i;++j)
for(int k=1;k<=m;++k){
int d=q[k]%i; if(d==0) d=i;
if(d>j) f[i][j]+=f[i-1][i-d+j]/m;
if(d<j) f[i][j]+=f[i-1][j-d]/m;
}
for(int i=1;i<=n;++i) printf("%.2lf%% ",f[n][i]*100);
return 0;
}