题目链接

树形\(dp\)多半是跑不过去的,可用矩阵快速幂解决

题目大意:给定一个无向图,\(0\)秒时机器人在\(1\)号点,每秒可以走到另一个相邻的点或者不动或者自爆,求\(t\)秒内行动方案数

矩阵快速幂


分析:首先把问题统一,不动我们连自环即可,自爆可以连单向边到虚拟点,虚拟点连自环,然后问题就变成了\(t\)秒后走到每个点的方案数之和

假设用\(f[t][u]\)表示在\(t\)秒时走到\(u\)点的方案数,显然\(f[t][u] = \sum f[t-1][v]\),有边\((u,v)\),然后假设我们知道当前的\(f\),把它构成一个矩阵

\(\begin{pmatrix}f(1),f(2)\dots f(n)\end{pmatrix}\)

然后我们发现将其乘上邻接矩阵\(G\)就可以得到下一秒的\(f\)值,然后就可以矩阵快速幂解决

#include <cstdio>
#include <cctype>
#include <cstring>
#include <vector>
using namespace std;
const int maxn = 32,mod = 2017;
inline int read(){
	int x = 0;char c = getchar();
	while(!isdigit(c))c = getchar();
	while(isdigit(c))x = x * 10 + c - '0',c = getchar();
	return x;
}
struct matrix{
	int val[maxn][maxn],x,y;
	matrix operator * (const matrix &rhs)const{
		matrix res;
		res.x = x;
		res.y = rhs.y;
		for(int i = 1;i <= res.x;i++)
			for(int j = 1;j <= res.y;j++)res.val[i][j] = 0;
		for(int i = 1;i <= res.x;i++)
			for(int j = 1;j <= res.y;j++)
				for(int k = 1;k <= y;k++)
					res.val[i][j] = (res.val[i][j] + val[i][k] * rhs.val[k][j]) % mod;
		return res;
	}
}G,ans;
int n,m,t,out;
inline matrix qpow(const matrix &a,int b){
	matrix res,base = a;
	res.x = res.y = a.x;
	for(int i = 1;i <= res.x;i++)
		for(int j = 1;j <= res.y;j++)
			res.val[i][j] = 0;
	for(int i = 1;i <= res.x;i++)
		res.val[i][i] = 1;
	while(b){
		if(b & 1)res = res * base;
		base = base * base;
		b >>= 1;
	}
	return res;
}
int main(){
	n = read() + 1,m = read();
	G.x = G.y = n;
	for(int u,v,i = 1;i <= m;i++)
		u = read(),v = read(),G.val[u][v] = G.val[v][u] = 1;
	t = read();
	for(int i = 1;i <= n;i++)G.val[i][i] = 1;
	for(int i = 1;i <= n - 1;i++)G.val[i][n] = 1;
	ans.x = 1,ans.y = n;
	ans.val[1][1] = 1;
	ans = ans * qpow(G,t);
	for(int i = 1;i <= n;i++)
		out = (out + ans.val[1][i]) % mod;
	printf("%d\n",out);
	return 0;
}

相关文章:

  • 2021-12-09
  • 2021-10-16
  • 2022-12-23
  • 2022-01-17
  • 2022-12-23
  • 2022-02-16
猜你喜欢
  • 2021-12-01
  • 2022-12-23
  • 2021-12-04
  • 2021-06-06
  • 2021-09-14
  • 2021-09-08
相关资源
相似解决方案