• 2015多校10 1006.CRB and Puzzle HDU5411(邻接矩阵求k长路条数,矩阵快速幂


    题意:有若干字符,现在要把它们连成一个字符串,每种字符后面只能接特定种类的字符,现在询问能连接出的长度小于等于m的字符串有多少种。

    思路:我们可以把这个转移关系看成一个图,如果字符a后面可以接b,那么从a向b连边。用邻接矩阵保存这个图。。。然后可以发现长度为m的字符串实际上是这个图中的一条长度为m(经过m个点)的路。那么可以想到一个经典结论:一个图中的k长路的条数等于这个图的邻接矩阵求k次幂后每项的和。

    但是这样我们并不能直接得到答案,每次只能求出所有m长路。这里有个技巧,可以求出一个矩阵的1到m次幂的和。也就是A+A^2+A^3+....+A^m,这个和最后再求每一个元素的和就是答案了。

    转移矩阵是这样的:

    A   0

    I    I

    这个矩阵直接求m次幂,用矩阵快速幂最终算法是O(n^3logm)的,最后左下角那个位置就是要求的幂和(可以手工验证下。。)

    PS:比赛的时候把mod写在了三重循环里面,其实,这个2015的mod很有深意啊。。。把mod写到第二重循环里面就过了啊。。卧槽。取模这么慢。。

    //#pragma comment(linker, "/STACK:102400000,102400000")
    #include <iostream>
    #include <map>
    #include <algorithm>
    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <vector>
    #include <queue>
    #include <stack>
    #include <functional>
    #include <set>
    #include <cmath>
    #define pb push_back
    #define PB pop_back
    #define fs first
    //#define se second
    #define sq(x) (x)*(x)
    #define IINF (1<<29)
    using namespace std;
    typedef long long ll;
    typedef pair<ll,ll> P;
    const int mod=2015;
    int sz;
    int mid[110][110];
    struct matrix{
        int m[110][110];
        matrix(){
            memset(m,0,sizeof m);
        }
        void mul(const matrix &b){
            memset(mid,0,sizeof mid);
            for(int i=0;i<sz;i++){
                for(int j=0;j<sz;j++){
                    for(int k=0;k<sz;k++){
                        mid[i][j]=(mid[i][j]+m[i][k]*b.m[k][j]);
                    }
                    mid[i][j]%=mod;
                }
            }
            for(int i=0;i<sz;i++){
                for(int j=0;j<sz;j++){
                    m[i][j]=mid[i][j];
                }
            }
        }
        void selfmul(){
            memset(mid,0,sizeof mid);
            for(int i=0;i<sz;i++){
                for(int j=0;j<sz;j++){
                    for(int k=0;k<sz;k++){
                        mid[i][j]=(mid[i][j]+m[i][k]*m[k][j]);
                    }
                    mid[i][j]%=mod;
                }
            }
            for(int i=0;i<sz;i++){
                for(int j=0;j<sz;j++){
                    m[i][j]=mid[i][j];
                }
            }
        }
    };
    matrix qpow(matrix x,ll p){
        matrix ans;
        for(int i=0;i<sz;i++){
            ans.m[i][i]=1;
        }
        while(p>0){
            if(p&1) ans.mul(x);
            x.selfmul();
            p>>=1;
        }
        return ans;
    }
    const int maxm=1e5+300;
    int T;
    int n,m;
    bool trans[60][60];
    int main(){
        freopen("/home/files/CppFiles/in","r",stdin);
        //freopen("/home/files/CppFiles/out","w",stdout);
        cin>>T;
        while(T--){
            memset(trans,0,sizeof trans);
            scanf("%d%d",&n,&m);
            sz=n*2;
            for(int i=1;i<=n;i++){
                int k;
                scanf("%d",&k);
                for(int j=0;j<k;j++){
                    int x;
                    scanf("%d",&x);
                    trans[i-1][x-1]=1;
                }
            }
            matrix tt;
            for(int i=0;i<n;i++){
                for(int j=0;j<n;j++){
                    tt.m[i][j]=trans[i][j];
                }
            }
            for(int i=n;i<2*n;i++){
                int j=i-n;
                tt.m[i][j]=1;
                tt.m[i][i]=1;
            }
            matrix ans=qpow(tt,m);
            int sum=0;
            for(int i=n;i<2*n;i++){
                for(int j=0;j<n;j++)
                sum=(sum+ans.m[i][j])%mod;
            }
            printf("%d
    ",(sum+1)%mod);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    Zabbix学习
    Ping 不通的原因分析
    【FAQ】P3. 为什么 torch.cuda.is_available() 是 False
    【PyTorch教程】P2. Python编辑器的选择、安装及配置
    PyTorch环境配置及安装
    更改文件夹图标
    卸载OpenIV
    一次写文,多平台直接粘贴&打造最流畅的写作流程
    Python字符串中删除特定字符
    Python字符串中添加、插入特定字符
  • 原文地址:https://www.cnblogs.com/Cw-trip/p/4746307.html
Copyright © 2020-2023  润新知