[SDOI2009]HH去散步 「矩阵乘法计数」

计数问题也许可以转化为矩阵乘法形式

比如若该题没有不能在一条边上重复走的条件限制,那么直接将邻接矩阵转化为矩阵乘法即可

矩阵乘法计数

对于计数问题,若可以将 \(n\) 个点表示成 \(n \times n\) 的矩阵,并且可以保证中途转移对象不会变化,即可用矩阵乘法计数

至于该题

那么考虑该题,加入了不能重复在一条边上走的限制,那么最简单的思想就是拆点,并且让改点屏蔽掉当前方向,但是如果考虑边,一条无向边可以拆成两条有向边,那拆出来的就比点少很多了,故考虑点边转化

那么只要在起始点加一条超级源边,同样矩阵乘法即可统计答案

代码

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

#define MOD 45989

using namespace std;

typedef long long LL;

const int MAXN = 50 + 10;
const int MAXM = 120 + 10;

struct LinkedForwardStar {
	int to;

	int next;
} ;

LinkedForwardStar Link[MAXM];
int Head[MAXN]= {0};
int size = 1;

void Insert (int u, int v) {
	Link[++ size].to = v;
	Link[size].next = Head[u];

	Head[u] = size;
}

int N, M, K;
int st, ed;

struct Matrix {
	LL a[MAXM][MAXM];

	void init () {
		for (int i = 1; i <= size; i ++)
			for (int j = 1; j <= size; j ++)
				a[i][j] = 0;
	}
	Matrix operator * (const Matrix& p) const {
		Matrix newmat;
		newmat.init ();
		for (int i = 1; i <= size; i ++)
			for (int j = 1; j <= size; j ++)
				for (int k = 1; k <= size; k ++)
					newmat.a[i][j] = (newmat.a[i][j] + a[i][k] * p.a[k][j] % MOD) % MOD;
		return newmat;
	}
} ;
Matrix mats, bem;

LL power (int p) {
	while (p) {
		if (p & 1)
			mats = mats * bem;
		bem = bem * bem;
		p >>= 1;
	}
	LL ans = 0;
	for (int i = Head[ed]; i; i = Link[i].next)
		ans = (ans + mats.a[1][i ^ 1]) % MOD;
	return ans;
}

int getnum () {
	int num = 0;
	char ch = getchar ();

	while (! isdigit (ch))
		ch = getchar ();
	while (isdigit (ch))
		num = (num << 3) + (num << 1) + ch - '0', ch = getchar ();

	return num;
}

int main () {
	N = getnum (), M = getnum (), K = getnum (), st = getnum () + 1, ed = getnum () + 1;
	for (int i = 1; i <= M; i ++) {
		int u = getnum () + 1, v = getnum () + 1;
		Insert (u, v), Insert (v, u);
	}
	for (int i = Head[st]; i; i = Link[i].next)
		bem.a[1][i] = 1;
	for (int i = 2; i <= size; i ++) {
		int v = Link[i].to;
		for (int j = Head[v]; j; j = Link[j].next) {
			if ((j ^ 1) == i)
				continue;
			bem.a[i][j] = 1;
		}
	}
	for (int i = 1; i <= size; i ++)
		mats.a[i][i] = 1;
	LL ans = power (K);
	cout << ans << endl;

	return 0;
}

/*
4 5 3 0 0
0 1
0 2
0 3
2 1
3 2
*/
posted @ 2019-01-22 18:16  Colythme  阅读(204)  评论(0编辑  收藏  举报