【luogu5550】【矩阵乘法】【快速幂】Chino的数列

题目背景

没有背景

我写不出来了qwq

题目描述

Chino给定了 n n n个数 a 1 . . . a n a_1...a_n a1...an,给定常数 s , m s,m s,m,她会轮流对这 n n n个数做 k k k组操作,每组操作包含以下几步:

1. s w a p ( a s , a m ) 1.swap(a_s,a_m) 1.swap(as,am)(交换 a s a_s as , a m a_m am)

2. 2. 2. n n n个数都向前平移一位(第 1 1 1个移动到第 n n n个位置上)

Chino想知道, k k k组操作后,这 n n n个数分别是多少?

Orz yky,dyh,wjk,jjy,cxr,gsy,cpy,zcy,tyz,yy,hz,zhr,ygg

输入格式

第一行,四个数, n , s , m , k n,s,m,k n,s,m,k

接下来一行 n n n个数,分别代表 a 1 , a 2 . . . a n a_1,a_2...a_n a1,a2...an

输出格式

输出一行, n n n个数,分别代表 a 1 , a 2 . . . a n a_1,a_2...a_n a1,a2...an

输入输出样例
输入 #1
4 1 2 3
1 2 3 4
输出 #1
1 2 3 4
说明/提示

对于 40 % 40\% 40%的数据, 1 ≤ k ≤ 1 0 7 1 \leq k \leq 10^7 1k107
对于 100 % 100\% 100%的数据, 1 ≤ n ≤ 80 1 \leq n \leq 80 1n80 1 ≤ s < m ≤ n 1 \leq s < m\leq n 1s<mn 1 ≤ k ≤ 1 0 18 1 \leq k \leq 10^{18} 1k1018
所有数字均在 l o n g l o n g long long longlong以内


解题思路

A = [ 1 2 3 4 ] A = \begin{bmatrix} 1& 2 & 3 & 4 \end{bmatrix} A=[1234]
考虑构造一个操作矩阵
在把数字进行操作时,只进行向前的操作

f[i][check(i - 1)] = 1//如果x > 0,check(x) = x; 如果x = 0,check(x) = n

B = [ 0 0 0 1 1 0 0 0 0 1 0 0 0 0 1 0 ] B = \begin{bmatrix} 0& 0 & 0 & 1\\ 1& 0 & 0 & 0\\ 0& 1 & 0 & 0\\ 0& 0 & 1 & 0 \end{bmatrix} B=0100001000011000
那么再把特殊情况s和m处理一下

x = i;
if (x == s) x = m;
if (x == m) x = s;
f[x][check(i - 1)] = 1;

B = [ 1 0 0 0 0 0 0 1 0 1 0 0 0 0 1 0 ] B =\begin{bmatrix} 1& 0 & 0 & 0\\ 0& 0 & 0 & 1\\ 0& 1 & 0 & 0\\ 0& 0 & 1 & 0 \end{bmatrix} B=1000001000010100

那么问题转换为了 A ∗ B k A *B^k ABk


Code

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

using namespace std;

struct DT{
    
    
	int n, m;
	ll aed[100][100];
}A, B, M;
int n, k, l, x;
ll m;

int check (int x){
    
    
	if (x == 0)
		return n;
	else return x; 
}

DT operator *(DT a, DT b){
    
    //矩阵乘法
	DT c;
	memset (c.aed, 0, sizeof (c.aed));
	c.n = a.n, c.m = b.m;
	for (int k = 1; k <= a.m; k++)
		for (int i = 1; i <= a.n; i++)
			for (int j =1; j <= b.m; j++)
				c.aed[i][j] += a.aed[i][k] * b.aed[k][j];
	return c;
}

void power (ll m){
    
    //快速幂
	if (m == 1)
	{
    
    
		M = B;
		return;
	}
	power (m / 2);
	M = M * M;
	if (m % 2)
		M = M * B; 
}

int main(){
    
    
	scanf ("%d%d%d%lld", &n, &k, &l, &m);
	A.n = 1, A.m = n, B.n = n, B.m = n;
	for (int i = 1; i <= n; i++)
		scanf ("%lld", &A.aed[1][i]);
	for (int i = 1; i <= n; i++)//构造操作矩阵
	{
    
    
		x = i;
		if (i == k) x = l;
		if (i == l) x = k;
		
		B.aed[x][check (i - 1)] = 1;
	}
	/*for (int i = 1; i <= n; i++)
	{
		for (int j = 1; j <= n; j++)
			printf ("%lld ", B.aed[i][j]);
		printf ("\n");
	}*/
	power (m);
	A = A * M;
	for (int i = 1; i <= n; i++)
		printf ("%lld ", A.aed[1][i]);
}

猜你喜欢

转载自blog.csdn.net/qq_39940018/article/details/111395723
今日推荐