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]],然后变成幂运算之后就可以加速了。多次乘以相同的数值其实就是幂运算(一个数就是整数幂,多个数的式子就是矩阵幂)