• BZOJ4887: [Tjoi2017]可乐 矩阵快速幂


    Description

    加里敦星球的人们特别喜欢喝可乐。因而,他们的敌对星球研发出了一个可乐机器人,并且
    放在了加里敦星球的1号城市上。这个可乐机器人有三种行为:停在原地,去下一个相邻的
    城市,自爆。它每一秒都会随机触发一种行为。现在给出加里敦星球城市图,在第0秒时可
    乐机器人在1号城市,问经过了t秒,可乐机器人的行为方案数是多少?
     

    Input

    第一行输入两个正整数N,M表示城市个数,M表示道路个数。(1≤N≤30,0≤M≤100)
    接下来M行输入u,v表示u,v之间有一条道路。
    (1≤u,v≤n)保证两座城市之间只有一条路相连。
    最后输入时间t。1<t≤10^6

    Output

     输出可乐机器人的行为方案数,答案可能很大,请输出对2017取模后的结果。

    Sample Input

    3 2
    1 2
    2 3
    2

    Sample Output

    8

    Solution

    第一次做到这种以图的形式的递推用矩阵乘法优化的

    貌似是套路题但是我不会啊T_T

    于是观摩了一波题解弄懂了这种类型的题目

    一般是这种T很大N很小的题目就可以矩阵乘法优化

    要求走T次就是对邻接矩阵自乘T次...

    /**************************************************************
        Problem: 4887
        User: henryy
        Language: C++
        Result: Accepted
        Time:80 ms
        Memory:1456 kb
    ****************************************************************/
     
    #include <bits/stdc++.h>
     
    using namespace std ;
     
    #define mod 2017
     
    int n , m ;
    struct matrix {
        int m[ 100 ][ 100 ] ;
        matrix() {
            memset( m , 0 , sizeof( m ) ) ;
        }
        int *operator[] ( int a ) { return m[ a ] ; } 
        matrix operator * ( matrix &x ) {
            matrix ans ;
            memset( ans.m , 0 , sizeof( ans.m ) ) ;
            for( int i = 0 ; i <= n ; i ++ ) {
                for( int j = 0 ; j <= n ; j ++ ) {
                    for( int k = 0 ; k <= n ; k ++ ) {
                        ans[ i ][ j ] = (ans[ i ][ j ] + m[ i ][ k ] * x[ k ][ j ] ) % mod ;
                    }
                }
            }
            return ans ;
        }
    } a ;
     
    matrix power( matrix x , int b ) {
        matrix ans , base = x ;
        for( int i = 0 ; i <= n ; i ++ ) ans[ i ][ i ] = 1 ;
        while( b ) {
            if( b & 1 ) ans = ans * base ;
            base = base * base ;
            b >>= 1 ;
        }
        return ans ;
    }
     
    int main() {
        scanf( "%d%d" , &n , &m ) ;
        for( int i = 1 ; i <= m ; i ++ ) {
            int x , y ;
            scanf( "%d%d" , &x , &y ) ;
            a[ x ][ y ] = a[ y ][ x ] = 1 ;
        }
        int t ;
        scanf( "%d" , &t ) ;
        for( int i = 0 ; i <= n ; i ++ ) a[ i ][ i ] = a[ i ][ 0 ] = 1 ;
        a = power( a , t ) ;
        int ans = 0 ;
        for( int i = 0 ; i <= n ; i ++ ) {
            ans = ( ans + a[ 1 ][ i ] ) % mod ;
        }
        printf( "%d
    " , ans ) ;
    }
  • 相关阅读:
    按属性分割要素
    python os.path模块
    用数组显示裴波那契数列
    计算两位数的加减乘除
    输入一串数字统计0到9每个数字的个数
    开辟新空间输入成绩
    关系表达式、条件表达式、逻辑表达式
    变量、函数和程序控制
    哥德巴赫定理
    找出二维数组中最大的值
  • 原文地址:https://www.cnblogs.com/henry-1202/p/BZOJ4887.html
Copyright © 2020-2023  润新知