概率dp刷题

CF717D Dexterina’s Lab

  • 题意:有一个 \(n\) 堆石子的 \(nim\) 游戏,石子数量从 \(0\)\(x\) 有一个概率 \(p_i\) ,代表了一堆石子数量为 \(i\) 的数量。求先手必赢的概率。
  • 题解:首先nim显然的是 \(nim\) 异或和为 \(0\) 是必输,然后可以构造 \(A\) 矩阵

\(A =\begin{bmatrix} p[0 \oplus 0 ] &p[0 \oplus 1] & p[0 \oplus 2]\\ p[1 \oplus 0 ] &p[1 \oplus 1] & p[1 \oplus 2]\\ p[2 \oplus 0 ] &p[2 \oplus 1] & p[2 \oplus 2] \end{bmatrix}\)

\(ans\) 矩阵就是 \(ans = \begin{bmatrix} dp[0] &0 & 0\\ dp[1] &0 & 0\\ dp[2] &0 & 0 \end{bmatrix}\)
\(ans_{1, j}\) 代表的意思是,在这一次,\(dp[j]\) ,即游戏出现他们异或和为\(j\) 情况的概率。

  • 代码:
#include<bits/stdc++.h>
#pragma comment(linker, "/STACK:102400000,102400000")
using namespace std;
typedef long long ll;
typedef long double ld;
const ll N = 129;
const ll inf = 0x3f3f3f3f;
ld pp[N];
const ll maxn = 10;
struct Matrix {
   ld a[maxn][maxn];
   int n;
   Matrix (int sz, int kind) {
       this->n = sz;
       for (int i = 0; i < sz; i ++) {
           for (int j = 0; j < sz; j ++) {
               a[i][j] = 0;
           }
       }
       for (int i = 0; i < sz; i ++) {
           a[i][i] = kind;
       }
   }
   Matrix operator*(Matrix rhs)const {
       Matrix ret(N - 1, 0);
       for (int i  = 0; i < n; i ++) {
           for (int j = 0; j < n; j ++) {
               for (int k = 0; k < n; k ++) {
                   ret.a[i][j] += a[i][k] * rhs.a[k][j];
               }
           }
       }
       return ret;
   }
   void out() {
       for (int i = 0; i < 5 ;i ++) {
           for (int j = 0; j < 5; j ++) {
               cout << a[i][j] << " ";
           }
           cout << endl;
       }
   }
} A(maxn - 1, 0);
Matrix q_pow( int k) {
   Matrix ret = {N - 1, 1};
   Matrix x = A;
   while (k) {
       if (k & 1) {
           ret = ret * x;
       }
       k >>= 1;
       x = x * x;
   }
   return ret;
}
void solve() {
   int n, x;
   cin >> n >> x;
   for (int i = 0; i <= x; i ++) {
       cin >> pp[i];
   }
   cout << fixed<<setprecision(10);
   for (int i = 0; i <= N-2; i ++) {
       for (int j = 0; j <= N-2; j ++) {
           A.a[i][j] = pp[j ^ i];
           
       }
   }
   Matrix res = q_pow( n);
   Matrix d = Matrix(N - 1, 0);
   d.a[0][0] = 1;
   res = d * res;
   cout << 1.0-res.a[0][0] << endl;
}
signed main() {
ll t = 1;//cin >> t;
while (t--) {
   solve();
}
}
posted @ 2021-08-04 21:04  u_yan  阅读(33)  评论(0编辑  收藏  举报