Luogu 2059 [JLOI2013]卡牌游戏 - 概率DP
Solution
设状态 $F[i][j] $为 还剩余 $i$ 个人时, 第 $j$ 个人 的胜率。
边界: $F[1][1] = 1$(只剩下一个人了)。
这样设置状态就能使 $i-1$ 个人的答案 转移到 $i$ 个人的答案上。
最后输出 $F[N][i]$ 。
状态转移:
1 int tmp = (a[k] - 1) % i + 1; 2 if (tmp == j) 3 continue; 4 tmp = j - tmp; 5 tmp = (tmp % i + i) % i; 6 f[i][j] += 1.0 / m * f[i - 1][tmp];
Code
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #define rd read() 5 #define db double 6 using namespace std; 7 8 const int N = 55; 9 10 int n, m, a[N]; 11 12 db f[N][N]; 13 14 int read() { 15 int X = 0, p = 1; char c = getchar(); 16 for (; c > '9' || c < '0'; c = getchar()) 17 if (c == '-') p = -1; 18 for (; c >= '0' && c <= '9'; c = getchar()) 19 X = X * 10 + c - '0'; 20 return X * p; 21 } 22 23 int main() 24 { 25 n = rd; m = rd; 26 for (int i = 1; i <= m; ++i) 27 a[i] = rd; 28 f[1][1] = 1; 29 for (int i = 2; i <= n; ++i) 30 for (int j = 1; j <= i; ++j) 31 for (int k = 1; k <= m; ++k) { 32 int tmp = (a[k] - 1) % i + 1; 33 if (tmp == j) 34 continue; 35 tmp = j - tmp; 36 tmp = (tmp % i + i) % i; 37 f[i][j] += 1.0 / m * f[i - 1][tmp]; 38 } 39 printf("%.2lf%%", f[n][1] * 100); 40 for (int i = 2; i <= n; ++i) 41 printf(" %.2lf%%", f[n][i] * 100); 42 putchar('\n'); 43 }