ZOJ 2794 Just Pour the Water 【矩阵快速幂】
给你n个杯子,每次有特定的到水规则,倒m次请问最后每个被子里还有多少水
我们很容易发现每次变化的规则相同,那么可以set 一个矩阵存放
然后多次倒水就相当于矩阵相乘,在m 范围达到(1<= M <= 1,000,000,000) 的情况下使用矩阵快速幂再好不过
这到题目注意的一点是,得使用Double 变量,如果使用FLoat会导致Wrong Answer
Source Code:
//#pragma comment(linker, "/STACK:16777216") //for c++ Compiler #include <stdio.h> #include <iostream> #include <fstream> #include <cstring> #include <cmath> #include <stack> #include <string> #include <map> #include <set> #include <list> #include <queue> #include <vector> #include <algorithm> #define Max(a,b) (((a) > (b)) ? (a) : (b)) #define Min(a,b) (((a) < (b)) ? (a) : (b)) #define Abs(x) (((x) > 0) ? (x) : (-(x))) #define MOD 1000000007 #define pi acos(-1.0) using namespace std; typedef long long ll ; typedef unsigned long long ull ; typedef unsigned int uint ; typedef unsigned char uchar ; template<class T> inline void checkmin(T &a,T b){if(a>b) a=b;} template<class T> inline void checkmax(T &a,T b){if(a<b) a=b;} const double eps = 1e-7 ; const int N = 22 ; const int M = 1100011*2 ; const ll P = 10000000097ll ; const int MAXN = 100000 ; const int INF = 0x3f3f3f3f ; const int MAX = 10500 ; double a[22]; int n, m; struct Mat { double mat[N][N]; }; Mat operator * (Mat a, Mat b){ Mat c; memset(c.mat, 0, sizeof(c.mat)); for(int k = 1; k <= n; ++k){ for(int i = 1; i <= n; ++i){ for(int j = 1; j <= n; ++j){ c.mat[i][j] += a.mat[i][k] * b.mat[k][j]; } } } return c; } Mat operator ^ (Mat a, int k){ Mat c; for(int i = 1; i <= n; ++i){ for(int j = 1; j <= n; ++j){ c.mat[i][j] = (i == j); //init } } for(; k; k >>= 1){ if(k & 1) c = c * a; a = a * a; } return c; } int main(){ std::ios::sync_with_stdio(false); int i, j, t, k, u, v, x, y, numCase = 0; int num; cin >> t; while(t--){ Mat real; memset(real.mat, 0, sizeof(real.mat)); cin >> n; for(i = 1; i <= n; ++i){ cin >> a[i]; } for(i = 1; i <= n; ++i){ cin >> k; real.mat[i][i] = (double)1; for(j = 1; j <= k; ++j){ cin >> num; real.mat[i][num] += (double)1 / (double)k; real.mat[i][i] -= (double)1 / (double)k; } } cin >> m; real = real ^ m; double ans[22]; memset(ans, 0, sizeof(ans)); for(i = 1; i <= n; ++i){ for(j = 1; j <= n; ++j){ ans[j] += a[i] * real.mat[i][j]; } } for(i = 1; i <= n; ++i){ if(i != n){ printf("%.2f ",ans[i]); } else{ printf("%.2f\n",ans[i]); } } } return 0; }