POJ 3744-Scout YYF I【概率DP+矩阵快速幂】

迈不过友情╰ 2023-06-02 15:56 196阅读 0赞

题意:有n个地方有地雷,给出来你下标,对于每个位置i, 你走到i+1的概率是p,走到i+2的概率是1-p,问你不被地雷炸的概率。

思路:这题转移方程很好想,就是f[i] = p * f[i - 1] + (1 - p) * f[i - 2], f[1] = 1.

但是由于n范围很大,我们考虑用矩阵快速幂来优化,我们将地雷按照下标分段,只要经过这一段我们不被地雷炸就行了,

  1. #include<cstdio>
  2. #include<cstring>
  3. #include<iostream>
  4. #include<algorithm>
  5. using namespace std;
  6. typedef long long ll;
  7. #define mid ((l + r) >> 1)
  8. const int maxn = 1e2 + 10;
  9. struct mat
  10. {
  11. static const int N = 2;
  12. double M[N][N];
  13. mat(ll v = 0)
  14. {
  15. memset(M, 0, sizeof(M));
  16. if(v) //可以初始化为单位矩阵
  17. for(int i = 0; i < N; ++i)
  18. M[i][i] = v;
  19. }
  20. mat operator * (const mat &b)
  21. {
  22. mat c;
  23. for(int i = 0; i < N; ++i)
  24. for(int j = 0; j < N; ++j)
  25. for(int k = 0; k < N; ++k)
  26. c.M[i][j] = c.M[i][j] + M[i][k] * b.M[k][j];
  27. return c;
  28. }
  29. friend mat operator ^ (mat a, ll n)
  30. {
  31. mat res(1);
  32. while(n)
  33. {
  34. if(n & 1)
  35. res = res * a;
  36. a = a * a;
  37. n >>= 1;
  38. }
  39. return res;
  40. }
  41. };
  42. int x[maxn];
  43. int main()
  44. {
  45. int n; double p;
  46. while(~scanf("%d%lf", &n, &p))
  47. {
  48. mat a, b;
  49. b.M[0][0] = p, b.M[0][1] = 1;
  50. b.M[1][0] = 1 - p, b.M[1][1] = 0;
  51. double ans = 1;
  52. for(int i = 1; i <= n; ++i)
  53. {
  54. scanf("%d", &x[i]);
  55. }
  56. sort(x + 1, x + n + 1);
  57. a = b ^ (x[1] - 1);
  58. ans *= (1 - a.M[0][0]);
  59. for(int i = 2; i <= n; ++i)
  60. {
  61. a = b ^ (x[i] - x[i - 1] - 1);
  62. ans *= (1 - a.M[0][0]);
  63. }
  64. printf("%.7f\n", ans);
  65. }
  66. return 0;
  67. }

发表评论

表情:
评论列表 (有 0 条评论,196人围观)

还没有评论,来说两句吧...

相关阅读