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;

}

 

你可能感兴趣的:(water)