[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

拿到这题一开始没什么头绪,然后一不小心手残点开了标签,然后就在正解的思路上奔腾。。。话说这题想不到真的挺。。。

我们考虑邻接矩阵的意义,假设一个邻接矩阵的边都是1,然后限定一个时间走1的长度,不难发现这个矩阵的k次幂就是走了k秒之后能到达每个点的路径数。

然后如果只能一直走的话就是计算出来即可。

那么它还可以停在原地,连一条自己到自己的边就可以了。

那么他还可以自爆。。。新建一个自爆点。。然后把每个点向这个点连一条有去无回的边,然后计算即可。

Code

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <iostream>
#include <cstdlib>
#include <cmath>
#include <string>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <set>
#include <map>
#define re register
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define mo 2017
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define ms(arr) memset(arr, 0, sizeof(arr))
const int inf = 0x3f3f3f3f;
struct mul{
    int k[35][35];
    mul(){
        memset(k,0,sizeof(k));
    }
};
mul a;
int n,t,ans,m;
mul operator *(mul a,mul b){
    mul q;
    for(re int i=1;i<=n+1;i++)
        for(re int j=1;j<=n+1;j++)
            for(re int k=1;k<=n+1;k++)
                q.k[i][j]=(q.k[i][j]+a.k[i][k]*b.k[k][j])%mo;
    return q;
}
mul kasumi(mul a,int k){
    mul rep;
    for(re int i=1;i<=n;i++)
        rep.k[i][i]=1;
    while(k){
        if(k&1) rep=rep*a;
        a=a*a;
        k>>=1;
    }
    return rep;
}
inline int read()
{
    int x=0,c=1;
    char ch=' ';
    while((ch>'9'||ch<'0')&&ch!='-')ch=getchar();
    while(ch=='-') c*=-1,ch=getchar();
    while(ch<='9'&&ch>='0')x=x*10+ch-'0',ch=getchar();
    return x*c;
}
int main() 
{
    n=read();m=read();
    for(re int i=1;i<=m;i++){
    	int x=read(),y=read();
    	a.k[x][y]=a.k[y][x]=1;
    }
    t=read();
    for(re int i=1;i<=n+1;i++)
    	a.k[i][i]=1,a.k[i][n+1]=1;
    a=kasumi(a,t);
    for(re int i=1;i<=n+1;i++)
    	ans=(ans+a.k[1][i])%mo;
    cout<<ans;
    return 0;
}
原文地址:https://www.cnblogs.com/victorique/p/9139690.html