浏览器标题切换
浏览器标题切换end
把博客园图标替换成自己的图标
把博客园图标替换成自己的图标end

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\n" , ans ) ;
}

 

posted @ 2018-11-06 14:28  henry_y  阅读(306)  评论(0编辑  收藏  举报