zoukankan      html  css  js  c++  java
  • POJ3735【矩阵快速幂】

    逛了一圈。。。觉得这篇讲的比较清楚:传送门~

    简要概括:

    1、线性代数的知识,单位矩阵的利用;(如果不知道单位矩阵的,先去补习一下线代,做几题行列式就会了);

    2、然后构造好矩阵以后,直接做M次乘积运算,然后利用一个[1, 0 , ... , 0 ]矩阵提取答案就好了,对,那个[1,0,..., 0 ] 就是获取答案的作用。

    PS

    以前的矩阵快速幂总是这样写的:先构造一个矩阵,然后跑一发矩阵快速幂,然后这个矩阵a乘以另一个矩阵b就会得出答案,而答案矩阵往往会包括前一个答案的值。所以自己就有点不知所措。【这里写自己的智障困惑。。】


    #include <iostream>
    #include <stdio.h>
    #include <string.h>
    #include <algorithm>
    using namespace std;
    typedef long long LL;
    
    struct asd{
        LL a[110][110];
    };
    int n;
    
    asd mul(asd a, asd b)
    {
        asd ans;
        memset(ans.a,0,sizeof(ans.a));
        for(int k=0;k<=n;k++)
            for(int i=0;i<=n;i++)
                if(a.a[i][k])
                    for(int j=0;j<=n;j++)
                        ans.a[i][j]+=a.a[i][k]*b.a[k][j];
    
        return ans;
    }
    
    asd quickmul(int g,asd x)
    {
        asd ans;
        memset(ans.a,0,sizeof(ans.a));
        for(int i=0;i<=n;i++)
            ans.a[i][i]=1;
        while(g)
        {
            if(g&1) ans=mul(ans,x);
            x=mul(x,x);
            g>>=1;
        }
        return ans;
    }
    
    asd init(int k)
    {
        asd tmp;
        memset(tmp.a,0,sizeof(tmp.a));
        for(int i=0;i<=n;++i)
            tmp.a[i][i]=1;
    
        char x[5];
        int a,b;
        while(k--)
        {
            scanf("%s",x);
            if(x[0]=='g')
            {
                scanf("%d",&a);
                tmp.a[0][a]++;
            }
            else if(x[0]=='s')
            {
                scanf("%d%d",&a,&b);
                for(int i=0;i<=n;i++)
                    swap(tmp.a[i][a],tmp.a[i][b]);
            }
            else
            {
                scanf("%d",&a);
                for(int i=0;i<=n;i++)
                    tmp.a[i][a]=0;
            }
        }
        return tmp;
    }
    
    int main()
    {
        int m,k;
        asd ans,tmp;
        while(~scanf("%d%d%d",&n,&m,&k))
        {
            if((!n)&&(!m)&&(!k))
                break;
            tmp=init(k);
            ans=quickmul(m,tmp);
            memset(tmp.a,0,sizeof(tmp.a));
            tmp.a[0][0]=1;
            ans=mul(tmp,ans);
            for(int i=1;i<=n;i++)
            {
                if(i!=1) printf(" ");
                printf("%lld",ans.a[0][i]);
            }
            puts("");
        }
        return 0;
    }


  • 相关阅读:
    springboot项目使用AOP切面记录用户操作日志
    SpringBoot之——log4j日志配置案例
    IDEA--IDEA debug断点调试技巧
    LINUX FG、BG、JOBS命令用法
    消息队列学习记录
    JDK1.8下载与安装以及配置环境变量
    mysql 时间戳转换为年月日时分秒
    Java关于ExecutorService线程池的使用简介
    idea实现热部署
    MySQL 行行比较sql写法
  • 原文地址:https://www.cnblogs.com/keyboarder-zsq/p/6216813.html
Copyright © 2011-2022 走看看