• bzoj1875 [SDOI2009]HH去散步——矩阵快速幂


    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1875

    有个限制是不能走回头路,比较麻烦;

    所以把矩阵中的元素设成边的经过次数,单向边之间就好转移了;

    最后从单向边的经过次数得到点的路径方案数。

    代码如下:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    int const mod=45989;
    int n,m,T,A,B,head[25],ct=1,tot;
    struct N{
        int hd,to,next;
        N(int h=0,int t=0,int n=0):hd(h),to(t),next(n) {}
    }edge[125];
    struct Matrix{
        int a[125][125];
        Matrix(){memset(a,0,sizeof a);}//
        Matrix operator * (const Matrix &y) const
        {
            Matrix x;
            for(int i=1;i<=ct;i++)
                for(int k=1;k<=ct;k++)
                    for(int j=1;j<=ct;j++)
                        (x.a[i][j]+=a[i][k]*y.a[k][j])%=mod;
            return x;
        }
        void init()
        {
            for(int i=1;i<=ct;i++)a[i][i]=1;
        }
    }tr,ans;
    Matrix operator ^ (Matrix x,int y)
    {
        Matrix ret; ret.init();
        for(int i=y;i;i>>=1,x=x*x)
            if(i&1)ret=ret*x;//i 而不是 y!!!
        return ret;
    }
    void add(int x,int y){edge[++ct]=N(x,y,head[x]); head[x]=ct;}
    int main()
    {
        scanf("%d%d%d%d%d",&n,&m,&T,&A,&B);
        for(int i=1,x,y;i<=m;i++)
        {
            scanf("%d%d",&x,&y);
            add(x,y); add(y,x);
        }
        for(int i=head[A];i;i=edge[i].next) ans.a[1][i]++;
        for(int i=2;i<=ct;i++)//2
            for(int j=2;j<=ct;j++)    
                if(edge[i].to==edge[j].hd && i!=(j^1)) tr.a[i][j]++;//
        ans=ans*(tr^(T-1));
        for(int i=head[B];i;i=edge[i].next)
            (tot+=ans.a[1][i^1])%=mod;
        printf("%d",tot);
        return 0;
    }
  • 相关阅读:
    N!的位数
    c语言memset()函数
    通宵教室(ACM水题)
    欧拉函数+素数筛
    快速幂+大数取模
    观光浏览
    插入类排序(直接插入排序)
    showDoc使用方法
    $_POST与input('post.')区别
    “三日”面试官心得
  • 原文地址:https://www.cnblogs.com/Zinn/p/9247298.html
Copyright © 2020-2023  润新知