oj練習---dp專題
阿新 • • 發佈:2018-12-14
1.POJ 3744 Scout YYF I
經典的dp模型,但是要用到快速矩陣冪加速,分段的思想
# include <stdio.h> # include <algorithm> # include <string.h> # include <iostream> using namespace std; int mines[15]; void matrixMulti(double a[2][2], double b[2][2]){ double i,j,k,l; i = a[0][0]*b[0][0]+a[0][1]*b[1][0]; j = a[0][0]*b[0][1]+a[0][1]*b[1][1]; k = a[1][0]*b[0][0]+a[1][1]*b[1][0]; l = a[1][0]*b[0][1]+a[1][1]*b[1][1]; a[0][0]=i,a[0][1]=j,a[1][0]=k,a[1][1]=l; } double quickPow(const double p, int x){ if(x == -1){ return 1.0; } double a[2][2] = {0, 1, 1-p, p}, res[2][2] = {1,0,0,1}; while(x){ //printf("this 3\n"); if(x&1){ matrixMulti(res, a); } x/=2; matrixMulti(a,a); } return res[0][1]*(1-p); } int main(){ int num; double p, result; while(scanf("%d%lf",&num, &p) != EOF){ memset(mines, 0, sizeof(mines)); for(int i = 1 ; i <= num; ++i){ scanf("%d", mines + i); } if(mines[1] == 1){ printf("%.7f\n", 0.0); continue; } mines[0] = 0; result = 1.0; sort(mines, mines+num+1); for(int i = 1; i <= num; ++i){ result *= quickPow(p, mines[i] - mines[i - 1] - 1); } if(result < 0){ result = 0; } if(result > 1){ result =1; } printf("%.7f\n", result); } return 0; }
心得:1.dp[i]=dp[i-2]*(1-p)+dp[i-1]*p,其實就是連續跟1-p/p相乘,自然想到矩陣加速。2.快速冪的思想,將O(n)降成O(lg(n))。
3.[0, 1; 1-p, p] * [dp[i-2]; dp[i-1]] = [dp[i-1]; dp[i]],然後變成冪運算之後就可以加速了。多次乘以相同的數值其實就是冪運算(一個數就是整數冪,多個數的式子就是矩陣冪)