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

    BZOJ_1875_[SDOI2009]HH去散步_矩阵乘法

    Description

    HH有个一成不变的习惯,喜欢饭后百步走。所谓百步走,就是散步,就是在一定的时间 内,走过一定的距离。 但
    是同时HH又是个喜欢变化的人,所以他不会立刻沿着刚刚走来的路走回。 又因为HH是个喜欢变化的人,所以他每
    天走过的路径都不完全一样,他想知道他究竟有多 少种散步的方法。 现在给你学校的地图(假设每条路的长度都
    是一样的都是1),问长度为t,从给定地 点A走到给定地点B共有多少条符合条件的路径

    Input

    第一行:五个整数N,M,t,A,B。
    N表示学校里的路口的个数
    M表示学校里的 路的条数
    t表示HH想要散步的距离
    A表示散步的出发点
    B则表示散步的终点。
    接下来M行
    每行一组Ai,Bi,表示从路口Ai到路口Bi有一条路。
    数据保证Ai != Bi,但不保证任意两个路口之间至多只有一条路相连接。 
    路口编号从0到N -1。 
    同一行内所有数据均由一个空格隔开,行首行尾没有多余空格。没有多余空行。 
    答案模45989。
    N ≤ 20,M ≤ 60,t ≤ 2^30,0 ≤ A,B

    Output

    一行,表示答案。

    Sample Input

    4 5 3 0 0
    0 1
    0 2
    0 3
    2 1
    3 2

    Sample Output

    4

    不能走刚刚经过的边比较难处理,考虑把边当做点。
    如果出点连上另一条边的入点就在转移矩阵上加上这个转移。
    只需保证这条边不转移到这条边的反向边。
    再建立S,T两个点,连到该连的边上。
    注意可能有重边。
     
    代码:
    // luogu-judger-enable-o2
    #include <stdio.h>
    #include <string.h>
    #include <algorithm>
    #define mod 45989
    int n,m,t,A,B,xx[123],yy[123];
    struct Mat {
        int v[123][123];
        Mat(){memset(v,0,sizeof(v));}
        Mat operator*(const Mat &x)const {
            Mat re;int i,j,k;
            for(i=1;i<=m;i++) {
                for(j=1;j<=m;j++) {
                    for(k=1;k<=m;k++) {
                        (re.v[i][j]+=v[i][k]*x.v[k][j]%mod)%=mod;
                    }
                }
            }
            return re;
        }
    };
    inline Mat qp(Mat x,int y) {
        Mat I;
        int i;
        for(i=1;i<=m;i++) I.v[i][i]=1;
        while(y) {
            if(y&1ll) I=I*x;
            x=x*x;
            y>>=1;
        }
        return I;
    }
    int main() {
        scanf("%d%d%d%d%d",&n,&m,&t,&A,&B); A++; B++;
        int i,x,y,j;
        for(i=1;i<=m;i++) {
            scanf("%d%d",&x,&y); x++; y++;
            xx[i]=x; yy[i]=y;
            xx[i+m]=y; yy[i+m]=x;
        }
        m*=2;
        Mat g;
        for(i=1;i<=m;i++) {
            if(xx[i]==A) {
                g.v[m+1][i]=1;
            }
            if(yy[i]==B) {
                g.v[i][m+2]=1;
            }
            for(j=1;j<=m;j++) if(yy[i]==xx[j]&&i!=j+m/2&&j!=i+m/2) {
                g.v[i][j]=1;
            }
        }
        m+=2;
        Mat T=qp(g,t+1);
        printf("%d
    ",T.v[m-1][m]);
    }
    
  • 相关阅读:
    中间件的应用
    报表和日志
    Cookie和Session
    表单的应用
    静态资源和Ajax请求
    导入导出EXEC
    DATEDIFF() 函数返回两个日期之间的时间
    解决echarts柱形图X轴标题显示不全的问题
    Sqlserver 游标 慢
    sql语句根据日期查询,本周,本月,本年,今日相关统计
  • 原文地址:https://www.cnblogs.com/suika/p/8902174.html
Copyright © 2011-2022 走看看