[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 ->爆炸
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=1∑n?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+矩阵快速幂)
AtCoder Beginner Contest 199 F - Graph Smoothing(图的邻接矩阵幂的意义,数学期望,矩阵快速幂)