【矩阵乘法】行为方案

链接

YbtOJ 6-1-3

题目描述

加里敦星球的人们特别喜欢喝可乐。因而,他们的敌对星球研发出了一个可乐机器人,并且放在了加里敦星球的 1 号城市上。这个可乐机器人有三种行为:停在原地,去下一个相邻的城市,自爆。它每一秒都会随机触发一种行为。现在给出加里敦星球城市图,在第 0 秒时可乐机器人在 1 号城市,问经过了 t 秒,可乐机器人的行为方案数是多少?

思路

构建邻接矩阵,答案就是这个矩阵的t次方的每一项之和,直接用快速幂加速就好了
自爆就连个0号点,然后留在原地就是每个点连个自环就好了

代码

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#define ll long long

using namespace std;

const ll mo = 2017;
ll n, m, t, u, v, Ans;

struct matrix
{
    
    
	int n, m;
	ll a[105][105];
}g, ans;

matrix operator *(matrix a, matrix b)
{
    
    
	matrix c;
	c.n = a.n;
	c.m = b.m;
	memset(c.a, 0, sizeof(c.a));
	for(int k = 0; k <= a.m; ++k)
	for(int i = 0; i <= c.n; ++i)
	for(int j = 0; j <= c.m; ++j)
		c.a[i][j] = (c.a[i][j] + (a.a[i][k] * b.a[k][j]) % mo);
	return c;
}

void ksm(ll t)
{
    
    
	memset(ans.a, 0, sizeof(ans.a));
	for(int i = 0; i <= ans.n; ++i) 
		ans.a[i][i] = 1;
	while(t) 
	{
    
    
		if(t & 1) ans = ans * g;
		g = g * g;
		t >>= 1;
	}
}

int main()
{
    
    
	scanf("%lld%lld", &n, &m);
	for(int i = 1; i <= m; ++i)
	{
    
    
		scanf("%lld%lld", &u, &v);	
		g.a[u][v] = g.a[v][u] = 1;
	}
	g.n = g.m = n;
	ans.n = ans.m = n;
	for(int i = 0; i <= n; ++i)
		g.a[i][i] = 1;
	for(int i = 1; i <= n; ++i)
		g.a[i][0] = 1;
	scanf("%lld", &t);
	ksm(t);
	for(int i = 0; i <= n; ++i)
		Ans = (ans.a[1][i] + Ans) % mo;
	printf("%lld", Ans % mo);
	return 0;
}

Je suppose que tu aimes

Origine blog.csdn.net/LTH060226/article/details/121573480
conseillé
Classement