[TJOI2017]可乐(矩阵快速幂)

Posted zhangbuang

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[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。

 


 


 

这道题我们可以从邻接矩阵的幂的意义考虑。

设现在有一个邻接矩阵AA。

那么A^kAk的意义是什么?(两个点之间若有边则A[u][v]=1A[u][v]=1)

floydfloyd算法的角度考虑,不难发现A^kAk的第ii行第jj列的数字含义是从ii到jj经过kk步的路径方案总数。

从这个角度考虑,这个点就有了一种做法。

首先将这个图的邻接矩阵建出来,然后直接算这个矩阵的kk次方。

最后统计sumlimits_{i=1}^{n}A[1][i]i=1n?A[1][i]就是答案。

那么在原地停留和自爆怎么处理?

在原地停留很简单,我们只要认为每个点都有一个从自己到自己的自环即可。

那自爆呢?

我们可以将自爆这个状态也看成一个城市,就设它为编号00。

我们在邻接矩阵上从每个点都向这个点连一条边,这个点除了自己外不连其他出边。

这样就满足了任何一个点随时可以自爆,且无法恢复到其他状态。

最后,统计答案。


 


 

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<cstdlib>
 4 #include<cctype>
 5 #include<cmath>
 6 #include<iostream>
 7 #include<algorithm>
 8 #include<vector>
 9 #include<set>
10 #include<map>
11 #include<queue>
12 #include<stack>
13 typedef long long ll;
14 typedef unsigned long long ull;
15 using namespace std;
16 const int P=2017;
17 struct Matrix{
18     int a[31][31];
19     inline Matrix operator * (const Matrix &rhs)
20     {
21         Matrix ret;
22         memset(&ret,0,sizeof ret);
23         for(int i=0;i<=30;i++)
24             for(int j=0;j<=30;j++)
25                 for(int k=0;k<=30;k++)
26                     (ret.a[i][j]+=a[i][k]*rhs.a[k][j]%P)%=P;
27         return ret;
28     }
29 }mp;
30 Matrix ksm(Matrix &a,int b)
31 {
32     Matrix ret;
33     memset(&ret,0,sizeof ret);
34     for(int i=0;i<=30;i++) ret.a[i][i]=1;
35     while(b)
36     {
37         if(b&1) ret=ret*a;
38         a=a*a;b>>=1;
39     }
40     return ret;
41 }
42 int u,v,n,m,t;
43 int main()
44 {
45     scanf("%d%d",&n,&m);
46     for(int i=1;i<=m;i++)
47     {
48         scanf("%d%d",&u,&v);
49         mp.a[u][v]=1;mp.a[v][u]=1;
50     }
51     for(int i=0;i<=n;i++)
52         mp.a[i][i]=1;
53     for(int i=1;i<=n;i++) mp.a[i][0]=1;
54     int ans=0;
55     scanf("%d",&t);
56     Matrix anss=ksm(mp,t);
57     for(int i=0;i<=n;i++) (ans+=anss.a[1][i])%=P;
58     printf("%d
",ans);
59 }

 

以上是关于[TJOI2017]可乐(矩阵快速幂)的主要内容,如果未能解决你的问题,请参考以下文章

Luogu 3758 [TJOI2017]可乐(有向图邻接矩阵幂的意义 矩阵快速幂)

[BZOJ4887][TJOI2017]可乐(DP+矩阵快速幂)

4887. [TJOI2017]可乐矩阵乘法

AtCoder Beginner Contest 199 F - Graph Smoothing(图的邻接矩阵幂的意义,数学期望,矩阵快速幂)

bzoj4887[Tjoi2017]可乐 矩阵乘法

P3758 [TJOI2017]可乐