TJOI2017 Coke (Quick Matrix Power)

Description

The robot starts at 1 1On the 1st city. The robot has three behaviors: staying in place, next to the next city, and self-destruct. It randomly triggers a behavior every second. Now give the picture, ask afterttIn t seconds, what is the number of robot actions?

1 < t ≤ 1 0 9 , 1 ≤ N ≤ 30 , 0 < M < 100 1<t \leq 10^{9}, 1 \leq N \leq 30,0<M<100 1<t109,1N30,0<M<100

Solution

The map is very small, first build the adjacency matrix. For stopping in place, let fi, i = 1 f_{i,i} = 1fi,i=1. For self-destruction, a virtual node can be built0 00 , then let all points connect to it with adirected edge, that is,fi, 0 = 1 f_{i,0} = 1fi,0=1

Consider the process of dp, let gi, j, k g_{i,j,k}gi,j,kFor slave iii tojjj is gonekkThe number of k- step plans, you can findkkThe k dimension can be rolled away. Then the initial state isgi, j = fi, j g_{i,j} = f_{i,j}gi,j=fi,j. Use Floyd's ideas and transfer to

f i , j = ∑ k = 1 n f i , k × f k , j f_{i,j} = \sum_{k=1}^n f_{i,k} \times f_{k,j} fi,j=k=1nfi,k×fk,j

It can be found that this is a matrix multiplication, so the matrix is ​​quickly exponentiated.

Time complexity O (n 3 log ⁡ t) O(n^3 \log t)O ( n3logt)

Code

Hang a template for matrix fast power

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 100 + 5, INF = 0x3f3f3f3f, mod = 1e9 + 7;
inline int read() {
    
    
	int x = 0, f = 0; char ch = 0;
	while (!isdigit(ch)) f |= ch == '-', ch = getchar();
	while (isdigit(ch)) x = (x << 3) + (x << 1) + (ch ^ 48), ch = getchar();
	return f ? -x : x;
}
int n;
struct mat {
    
    
	int m[N][N];
	mat() {
    
    
		memset(m, 0, sizeof(m));
		for (int i = 0; i < N; i++) m[i][i] = 1;
	}
};


mat mul(mat a, mat b) {
    
    
	mat c;
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= n; j++) {
    
    
			c.m[i][j] = 0; //Mention! 
			for (int k = 1; k <= n; k++) 
				c.m[i][j] += a.m[i][k] * b.m[k][j] % mod;
			c.m[i][j] %= mod;	
		}
	return c;
}
mat ksm(mat a, int k) {
    
    
	mat res;
	while (k) {
    
    
		if (k & 1) res = mul(res, a);
		k >>= 1;
		a = mul(a, a);
	}
	return res;
}
signed main() {
    
    
	n = read(); int k = read();
	
	mat a; 
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= n; j++)
			a.m[i][j] = read();
	mat ans = ksm(a, k);
	for (int i = 1; i <= n; i++) {
    
    
		for (int j = 1; j <= n; j++)
			printf("%lld ", ans.m[i][j]);
		puts("");
	}		
	return 0;
}

Guess you like

Origin blog.csdn.net/qq_39984146/article/details/107863056