• 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
    ",ans[i]);
                }
            }
        }
    
        return 0;
    }
  • 相关阅读:
    问题:android学习内容破碎,我个人关于如何学习android的一些个人经历
    问题:一球从某高度自由落下,每次落地后反跳回原高度的一半;再落下,求它在第n次落地时,共经过多少米?第n次反弹多高?
    问题:alias设置与删除
    问题:从键盘读取特定类型的数据(使用Scanner读取int类型)
    求一个数组当中最大(最小)值的两种计算方法
    Mysql5.7安装
    maven下载及安装
    Ubuntu下修改DNS重启也能用的方法
    删除CNNIC证书
    字符编码ASCII, Unicode和UTF-8概念扫盲
  • 原文地址:https://www.cnblogs.com/wushuaiyi/p/4322177.html
Copyright © 2020-2023  润新知