POJ3744——概率DP 矩阵快速幂优化——Scout YYF I
http://poj.org/problem?id=3744
矩阵快速幂:
利用DP的递推式
就本题来说 dp[i] = p*dp[i-1] + (1-p)*dp[i-2]
由于x非常大最大1亿,这样的话复杂度就为1亿
所以这里可以用矩阵的思想
[dp[i] dp[i-1] ] = [ dp[i-1] dp[i-2] ] | p 1 - p|
| 1 0 |
递推得到
n - 1
[dp[n] dp[n-1]] = [dp[1] dp[2] ] |p 1 - p|
|1 0 |
注意我这里分开了矩阵和行列式!!!
(由于忘了线代,纠结了四五天- - 一直以为最后一步还要做一次乘法)
题目说了第一步肯定走1 dp[1] = 1
然后就利用快速幂(只是把矩阵相乘用了这个思想优化)
11101
把所有乘法相当于变成了二进制,2^0 +2^2 + 2^3 + 2^4
如果有末尾1 那么乘上,每次把2自己翻倍
就是一开始 为2^0, 然后看见了最后这个1 总值*2^0 2^0 变成2^1
倒数第二个是0 总值还是原值 2*1 变成 2*2
......
要排序一下
这里注意当a[i] == a[i-1] 会出现幂为负数的情况,因为我这里写的是while(n) 这样就会出现死循环T了- - 特判掉。
还有最后输出要.7f..WA了
/************************************************ * Author :Powatr * Created Time :2015-8-31 13:16:26 * File Name :B.cpp ************************************************/ #include <cstdio> #include <algorithm> #include <iostream> #include <sstream> #include <cstring> #include <cmath> #include <string> #include <vector> #include <queue> #include <deque> #include <stack> #include <list> #include <map> #include <set> #include <bitset> #include <cstdlib> #include <ctime> using namespace std; #define lson l, mid, rt << 1 #define rson mid + 1, r, rt << 1 | 1 typedef long long ll; const int MAXN = 1e5 + 10; const int INF = 0x3f3f3f3f; const int MOD = 1e9 + 7; struct Matrix { double a[2][2]; void inti(){ a[0][0] = a[1][1] = 1; a[1][0] = a[0][1] = 0; } }; Matrix mul(Matrix a, Matrix b) { Matrix ans; for(int i = 0 ; i < 2; i++){ for(int j = 0; j < 2; j++){ ans.a[i][j] = 0; for(int k = 0 ; k < 2; k++){ if(a.a[i][k] == 0 || b.a[k][j] == 0) continue; ans.a[i][j] += a.a[i][k]*b.a[k][j]; } } } return ans; } Matrix pow_m(Matrix a, int n) { Matrix ans; ans.inti(); while(n){ if(n&1) ans = mul(ans, a); n >>= 1; a = mul(a, a); } return ans; } double dp[11]; int b[11]; int main(){ int n; double p; Matrix matrix; Matrix ret; while(~scanf("%d%lf", &n, &p)){ double sum = 1; for(int i = 1; i <= n; i++) scanf("%d", &b[i]); sort(b + 1, b + n + 1); matrix.a[0][0] = p; matrix.a[0][1] = 1 - p; matrix.a[1][0] = 1; matrix.a[1][1] = 0; ret = pow_m(matrix, b[1] - 1); dp[1] = ret.a[0][0]; sum *= (1 - dp[1]); for(int i = 2; i <= n; i++){ if(b[i] == b[i-1]) continue; ret = pow_m(matrix, b[i] - b[i-1]- 1); dp[i] = ret.a[0][0]; sum *= (1 - dp[i]); } printf("%.7f\n", sum); } return 0; }