zoukankan      html  css  js  c++  java
  • P2151 [SDOI2009]HH去散步 矩阵快速幂模板

    P2151 [SDOI2009]HH去散步

    题目描述

    HH有个一成不变的习惯,喜欢饭后百步走。所谓百步走,就是散步,就是在一定的时间 内,走过一定的距离。 但是同时HH又是个喜欢变化的人,所以他不会立刻沿着刚刚走来的路走回。 又因为HH是个喜欢变化的人,所以他每天走过的路径都不完全一样,他想知道他究竟有多 少种散步的方法。

    现在给你学校的地图(假设每条路的长度都是一样的都是1),问长度为t,从给定地 点A走到给定地点B共有多少条符合条件的路径

    输入输出格式

    输入格式:

    第一行:五个整数N,M,t,A,B。其中N表示学校里的路口的个数,M表示学校里的 路的条数,t表示HH想要散步的距离,A表示散步的出发点,而B则表示散步的终点。

    接下来M行,每行一组Ai,Bi,表示从路口Ai到路口Bi有一条路。数据保证Ai != Bi,但 不保证任意两个路口之间至多只有一条路相连接。 路口编号从0到N − 1。 同一行内所有数据均由一个空格隔开,行首行尾没有多余空格。没有多余空行。 答案模45989。

    输出格式:

    一行,表示答案。

    输入输出样例

    输入样例#1: 复制
    4 5 3 0 0
    0 1
    0 2
    0 3
    2 1
    3 2
    输出样例#1: 复制
    4

    说明

    对于30%的数据,N ≤ 4,M ≤ 10,t ≤ 10。

    对于100%的数据,N ≤ 50,M ≤ 60,t ≤ 2^30,0 ≤ A,B

    题解:

    按边构造矩阵快速幂裸题

    // luogu-judger-enable-o2
    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <algorithm>
    using namespace std;
    #define ll long long
    const ll mod = 45989;
    int n, gu[130], gv[130], c;
    struct Mat{
        ll w[125][125];
        void unit(){
            for(int i = 1; i <= c; i++)
                for(int j = 1; j <= c; j++)
                    w[i][j] = (i == j);
        }
        void init(){
            for(int i = 1; i <= c; i++)
                for(int j = 1; j <= c; j++)
                    w[i][j] = 0;
        }
        void print(){
            for(int i = 1; i <= c; i++){
                for(int j = 1; j <= c; j++)printf("%lld ", w[i][j]);
                puts("");
            }
        }
    }rec, p;
    
    
    Mat operator * (const Mat &s, const Mat &t){
        Mat a; a.init();
        for(int i = 1; i <= c; i++)
            for(int j = 1; j <= c; j++)
                for(int k = 1; k <= c; k++)
                    a.w[i][j] = (a.w[i][j] + s.w[i][k] * t.w[k][j]) % mod;
        return a;
    }
    Mat ksm(Mat a, int b){
        Mat ret;
        for(ret.unit(); b; b >>= 1, a=a*a)
            if(b&1) ret=ret*a;
        return ret;
    }
    
    int main(){
        int m, u, v, t, a, b;
        ll ans = 0;
        scanf("%d%d%d%d%d", &n, &m, &t, &a, &b);
        rec.init(); 
        c = m<<1;
        Mat f; f.init();
        
        for(int i = 1; i <= c; i+=2){
            scanf("%d%d", &gu[i], &gv[i]);
            gu[i+1] = gv[i], gv[i+1] = gu[i];
            if(gu[i] == a) f.w[i][1] = 1;
            if(gu[i+1] == a) f.w[i+1][1] = 1;
        }
        if(t == 0) return !printf("%d
    ", a != b);
        for(int i = 1; i <= c; i++)
            for(int j = 1; j <= c; j++){
                if(gv[i] == gu[j] && (i+1)/2 != (j+1)/2) rec.w[j][i] = 1;
            }
        //rec.print();
        rec = ksm(rec, t-1);
        //rec.print();
        f = rec * f;
        //f.print();
        for(int i = 1; i <= c; i++)
            if(gv[i] == b) ans = (ans + f.w[i][1]) % mod;
        printf("%lld
    ", ans);
    }
    View Code
  • 相关阅读:
    在循环中禁止remove/add
    [算法竞赛入门]WERTYU
    [算法竞赛入门]Tex Quotes
    [算法竞赛入门]竖式问题
    [算法竞赛入门]蛇形填数
    [C++面试]关于const的使用方法
    [C++面试]单例模式-设计模式
    [C++面试]C++的三种继承(public/protected/private继承)
    用微服务架构,有哪些好处?
    东软数据可视化分析, 已经方便成这样?!
  • 原文地址:https://www.cnblogs.com/EdSheeran/p/9904912.html
Copyright © 2011-2022 走看看