bzoj 4887 [Tjoi2017]可乐 矩阵乘法

题面

题目传送门

解法

比较裸的矩阵乘法

对于爆炸,我们可以将所有点全部连向0,但是0没有出边

对于在某一个城市停留,直接连一个自环即可

时间复杂度:\(O(n^3)\)

代码

#include <bits/stdc++.h>
#define Mod 2017
using namespace std;
template <typename node> void read(node &x) {
	x = 0; int f = 1; char c = getchar();
	while (!isdigit(c)) {if (c == '-') f = -1; c = getchar();}
	while (isdigit(c)) x = x * 10 + c - '0', c = getchar(); x *= f;
}
struct Matrix {
	int a[50][50];
	void Clear() {memset(a, 0, sizeof(a));}
};
int n, m;
Matrix operator * (Matrix x, Matrix y) {
	Matrix ret; ret.Clear();
	for (int k = 0; k <= n; k++)
		for (int i = 0; i <= n; i++)
			for (int j = 0; j <= n; j++)
				ret.a[i][j] = (ret.a[i][j] + x.a[i][k] * y.a[k][j] % Mod) % Mod;
	return ret;
}
Matrix operator ^ (Matrix x, int y) {
	Matrix ret = x; y--;
	while (y) {
		if (y & 1) ret = ret * x;
		y >>= 1, x = x * x; 
	}
	return ret;
}
int main() {
	read(n), read(m);
	Matrix ret; ret.Clear();
	for (int i = 1; i <= m; i++) {
		int x, y; read(x), read(y);
		ret.a[x][y] = ret.a[y][x] = 1;
	}
	for (int i = 0; i <= n; i++) ret.a[i][0] = ret.a[i][i] = 1;
	int t, ans = 0; read(t);
	ret = ret ^ t;
	for (int i = 0; i <= n; i++) ans = (ans + ret.a[1][i]) % Mod;
	cout << ans << "\n";
	return 0;
}

posted @ 2018-08-14 22:20  谜のNOIP  阅读(187)  评论(0编辑  收藏  举报