zoukankan      html  css  js  c++  java
  • [SDOI2009] HH去散步 (矩阵乘法)

    link

    $solution:$

    将边化为点后重新建矩阵,跑$T-1$幂即可(因为跑的是新边)。

    最后直接找与$x,y$所相连的边即可。

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<algorithm>
    #define int long long
    #define mod 45989
    using namespace std;
    inline int read(){
        int f=1,ans=0;char c=getchar();
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();}
        return f*ans;
    }
    const int MAXN=101;
    struct Matrix{
        int a[MAXN<<1][MAXN<<1];
        void init(){memset(a,0,sizeof(a));return;}
    }F,G;
    int cnt,n,m,A,B,T,sta[MAXN][MAXN<<1],End[MAXN<<1];
    Matrix operator*(Matrix x1,Matrix x2){
        Matrix x3;x3.init();
        for(int i=1;i<=(m<<1);i++)
            for(int k=1;k<=(m<<1);k++)
                for(int j=1;j<=(m<<1);j++) x3.a[i][j]+=x1.a[i][k]*x2.a[k][j],x3.a[i][j]%=mod;
        return x3;
    }
    Matrix ksm(Matrix a,int b){
        Matrix ans;ans.init();
        for(int i=1;i<=(m<<1);i++) ans.a[i][i]=1;
        while(b){
            if(b&1) ans=ans*a;
            a=a*a,b>>=1;
        }return ans;
    }int ans;
    int uu[MAXN<<1],vv[MAXN<<1];
    bool check(int idi,int idj){
        if(vv[idi]==uu[idj]) return 1;
        return 0;
    }
    signed main(){
        n=read(),m=read(),T=read(),A=read()+1,B=read()+1;
        for(int i=1;i<=m;i++){
            int u=read()+1,v=read()+1;
            if(v==B) End[++End[0]]=i;
            if(u==B) End[++End[0]]=i+m; 
            sta[u][++sta[u][0]]=i;
            uu[i]=u,vv[i]=v;
            sta[v][++sta[v][0]]=i+m;
            uu[i+m]=v,vv[i+m]=u;
        }F.init(),G.init();
        for(int i=1;i<=(m<<1);i++){
            for(int j=1;j<=(m<<1);j++) if(check(i,j)&&(i+m!=j&&j+m!=i)) G.a[i][j]=1;
        }
        //print(G);
        //printf("=========================
    ");
        F=ksm(G,T-1);
        //print(F);
        //for(int i=1;i<=End[0];i++) printf("End(%d):%d
    ",i,End[i]);
        //for(int i=1;i<=sta[A][0];i++) printf("sta(%d):%d
    ",i,sta[A][i]);
        for(int i=1;i<=sta[A][0];i++)
            for(int j=1;j<=End[0];j++) ans+=F.a[sta[A][i]][End[j]],ans%=mod;
        printf("%lld
    ",ans); 
    }
    View Code
  • 相关阅读:
    GPG实践
    keepass数据库保存密码
    基于xammp搭建自己的网页
    《信息安全专业导论》第12周学习总结
    《信息安全专业导论》第11周学习总结
    基于python中tkinter的计算机实现
    《信息安全专业导论》第10周学习总结
    俄罗斯方块
    小学四则运算编程实践
    链表
  • 原文地址:https://www.cnblogs.com/si-rui-yang/p/10601789.html
Copyright © 2011-2022 走看看