zoukankan      html  css  js  c++  java
  • 矩阵连乘

    DG之童年的游戏  矩阵连乘 + 坐标变换

    题目来源:

    http://acm.seu.edu.cn/oj/problem.php?id=49

    坐标变换为:

    所以我们知道 转移矩阵分别为:

    第i个人加1(eg.第2个人)

    1 0 0

    0 1 1

    0 0 1

    第2个人变0

    1 0 0

    0 0 0

    0 0 1

    第2个人与第1个人交换(第二行与第一行交换)

    0 1 0

    1 0 0

    0 0 1

    代码如下:

    #include <iostream>
    #include <algorithm>
    #include <stdlib.h>
    #include <stdio.h>
    #include <stack>
    #include <string>
    #include <string.h>
    #include<cstring>
    #include <algorithm>
    #include <stdlib.h>
    #include <vector>
    #include <set>
    #include <math.h>
    #include <cmath>
    #include <map>
    #include <queue>
    using namespace std ;
    typedef long long LL ;
    const int Max_N = 104;
    int  n ;
    
    struct Mat{     // 矩阵下标从1开始 - n
        LL elem[Max_N][Max_N];
        Mat(){ //全0矩阵
            memset(elem, 0, sizeof(elem));
        }
        void DigOne(){ //单位矩阵
            for(int i = 1 ; i <= n ; i++) elem[i][i] = 1 ;
        }
    };
    
    Mat operator * (Mat a , Mat b){
        Mat s;
        for(int i=1; i <= n  ; i++){
            for(int j=1; j <= n; j++){
                if(a.elem[i][j] == 0) continue ; //稀疏矩阵
                for(int k=1; k <= n ; k++){
                    s.elem[i][k] +=  a.elem[i][j] * b.elem[j][k];
                }
            }
        }
        return s;
    }
    
    Mat operator ^ (Mat x , int  y){
        Mat s ;
        s.DigOne() ;
        for(; y ; y >>= 1 , x = x * x){
            if(y&1) s = s * x ;
        }
        return s;
    }
    
    int main(){
        int  m , k ,  i , j , t ;
        char s[3];
        while(scanf("%d%d%d",&n,&m,&k)){
            if(n==0 && m==0 && k==0)
                break;
            n++ ;
            Mat O ;
            O.DigOne() ;
            for(t = 1 ; t <= k ; t++){
                scanf("%s",s);
                if(s[0] == 'a'){
                    scanf("%d" , &i);
                    Mat A ;
                    A.DigOne() ;
                    A.elem[i][n]=1;
                    O = A * O ;
                }
                else if(s[0] == 'b'){
                    scanf("%d",&i);
                    Mat A ;
                    A.DigOne() ;
                    A.elem[i][i]=0;
                    O = A * O ;
                }
                else{
                    scanf("%d%d", &i , &j);
                    Mat A ;
                    A.DigOne() ;
                    A.elem[i][i]=0  , A.elem[i][j]=1;
                    A.elem[j][i]=1  , A.elem[j][j]=0;
                    O = A * O ;
                }
            }
            O = O ^ m ;
            for(i=1 ; i< n-1 ; i++)
                printf("%lld ", O.elem[i][n]);
            printf("%lld
    ", O.elem[n-1][n]);
        }
        return 0;
    }

    poj 3070 Fibonacci    矩阵连乘 + mod 求余

    题目来源:
    http://poj.org/problem?id=3070

    代码如下:

    using namespace std ;
    typedef long long LL ;
    const double EPS = 1e-10;
    const int Max_N = 104;
    const int Mod = 10000;
    struct Mat{
        int mat[2][2];
        Mat operator * (Mat m){ // 矩阵相乘double型
            Mat ans={0, 0, 0, 0};
            for(int i = 0; i<2 ; i++)
                for(int j=0; j<2; j++)
                    if(mat[i][j] > EPS) // 剪枝
                        for(int k=0; k<2; k++)
                            ans.mat[i][k]= (ans.mat[i][k] +mat[i][j]*m.mat[j][k] ) % Mod ;
            return ans;
        }
    }unit={1,0,0,1};
    // 矩阵幂乘
    Mat operator ^(Mat m, int b){ // b>0
        Mat p = m,ans = unit;
        for(; b>0 ; b>>=1, p=p*p)
            if(b&1)
                ans=ans*p;
        return ans;
    }
    int main(){
        int n;
        while(scanf("%d",&n) && n!= -1){
            if(n == 0) {puts("0");continue;}
            if(n== 1)  {puts("1"); continue;}
            Mat res={1,1,1,0};
            res=res^(n-1);
            cout<<res.mat[0][0]<<endl;
        }
        return 0;
    }

     zoj  2853 Evolution    矩阵连乘  +  double 型

    题目来源:

    http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1853

    代码如下:

    const double EPS = 1e-12;
    const int Max_N = 202;
    int n;
    struct Mat{
        double elem[Max_N][Max_N];
        void read(){
            for(int i=0; i<n; i++){
                for(int j=0; j<n; j++)
                    printf("%lf ",elem[i][j]);
                puts("");
            }
    
        }
    
    };
    Mat Zero(){
        Mat ans;
        for(int i=0; i<n; i++){
            for(int j=0; j<n; j++){
                    ans.elem[i][j] = 0;
            }
        }
        return ans;
    }
    Mat One(){
        Mat ans;
        for(int i=0; i<n; i++){
            for(int j=0; j<n; j++){
                    ans.elem[i][j] = (i==j);
            }
        }
        return ans;
    }
    Mat operator * ( Mat a, Mat b){
        Mat ans; ans=Zero();
        for(int i=0; i<n; i++){
            for(int j=0; j<n; j++){
                    if( fabs(a.elem[i][j])>EPS  )
                        for(int k=0; k<n; k++){
                            ans.elem[i][k] += a.elem[i][j] * b.elem[j][k];
                        }
            }
        }
        return ans;
    }
    Mat operator ^ ( Mat x, int y){
        Mat ans; ans = One();
        for(; y ; y>>=1, x= x*x)
            if(y & 1)
                ans=ans*x;
        return ans;
    }
    double data[Max_N];
    int main(){
        int m,t,x,y;
        double p;
        while(scanf("%d%d",&n,&m)){
            if(n==0 && m==0)
                break;
            Mat res;
            res=One();
            for(int i=0; i<n; i++)
                scanf("%lf",&data[i]);
            scanf("%d",&t);
            while(t--){
                scanf("%d%d%lf",&x,&y,&p);
                res.elem[y][x] +=p;
                res.elem[x][x] -=p;
            }
           // res.read();
            res = res^m;
            double sum=0;
    
            for(int i=0; i<n; i++){
                sum += res.elem[n-1][i]*data[i];
            }
            printf("%.0lf
    ",sum);
        }
    
        return 0;
    }
  • 相关阅读:
    【HDU4676】Sum Of Gcd(莫队+欧拉函数)
    【BZOJ5084】hashit(后缀自动机水过)
    【HHHOJ】ZJOI2019模拟赛(十三)03.10 解题报告
    【BZOJ2127】happiness(网络流)
    【CCPC-Wannafly Winter Camp Day4 (Div1) J】跑跑跑路(爬山算法)
    【CCPC-Wannafly Winter Camp Day4 (Div1) H】命命命运(概率DP)
    2019.03.09 ZJOI2019模拟赛 解题报告
    关闭Android/iPhone浏览器自动识别数字为电话号码
    border-radius 在安卓手机竟然不完美支持
    validate.plugin.js 验证插件
  • 原文地址:https://www.cnblogs.com/zn505119020/p/3669972.html
Copyright © 2011-2022 走看看