[洛谷P3758][TJOI2017]可乐

题目描述###

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

输入输出格式###

输入格式####

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

输出格式####

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

输入输出样例###

输入样例#1####

3 2
1 2
2 3
2

输出样例#1####

8

说明###

【样例解释】

1 ->爆炸
1 -> 1 ->爆炸
1 -> 2 ->爆炸
1 -> 1 -> 1
1 -> 1 -> 2
1 -> 2 -> 1
1 -> 2 -> 2
1 -> 2 -> 3

【数据范围】

对于20%的pn,有1 < t ≤ 1000
对于100%的pn,有1 < t ≤ 10^6。


想法##

很显然的dp
n这么小,可以矩阵加速
进行快速幂的矩阵共n+1列,前n列为某个点与其他点的连接情况,最后一列全是1,计算某一秒自爆的方案数


代码##

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>

#define P 2017

using namespace std;

const int N = 35;

struct matrix{
    int a[N][N];
    void clear(){
        for(int i=1;i<N;i++)
            for(int j=1;j<N;j++)
                a[i][j]=(i==j);
    }
    matrix operator * (const matrix &b) const{
        matrix c;
        for(int i=1;i<N;i++)
            for(int j=1;j<N;j++){
                c.a[i][j]=0;
                for(int k=1;k<N;k++)
                    c.a[i][j]=(c.a[i][j]+(a[i][k]*b.a[k][j])%P)%P;
            }
        return c;
    }
};

int n,m,t;
matrix map;

matrix pow_mod(matrix b,int x){
    matrix ret;
    ret.clear();
    while(x){
        if(x&1) ret=ret*b;
        b=b*b;
        x>>=1;
    }
    return ret;
}

int main()
{
    int u,v;
    scanf("%d%d",&n,&m);
    map.clear();
    for(int i=0;i<m;i++){
        scanf("%d%d",&u,&v);
        map.a[u][v]=map.a[v][u]=1;
    }
    for(int i=1;i<=n+1;i++)
        map.a[i][n+1]=1;
    scanf("%d",&t);
    
    matrix a;
    memset(a.a,0,sizeof(a.a));
    a.a[1][1]=1;
    a=a*pow_mod(map,t);
    
    int ans=0;
    for(int i=1;i<=n+1;i++)
        ans=(ans+a.a[1][i])%P;
    printf("%d\n",ans);
    
    return 0;
}
posted @ 2018-01-29 20:28  秋千旁的蜂蝶~  阅读(137)  评论(0编辑  收藏  举报