思路: 構造矩陣+矩陣快速冪 分析: 1 題目的意思是有n個人構成一個圈,每個人初始的有ai個蘋果,現在做m次的游戲,每一次游戲過後第i個人能夠增加R*A(i+n-1)%n+L*A(i+1)%n 個蘋果(題目有錯),問m輪游戲過後每個人的蘋果數 2 根據題目的意思我們能夠列出一輪過後每個人的蘋果數 a0 = a0+R*an-1+L*a1 a1 = a1+R*a0+L*a2 ............................. an-1 = an-1+R*an-2+L*a0 3 根據第二條思路我們可以構造出如下的矩陣 1 L 0 ...... R a0 a0' R 1 L ......... * a1 a1' ................... .... = ...... ...........R 1 L an-2 an-2' L ...........R 1 an-1 an-1' 4 那麼根據3我們可以利用矩陣快速冪求出最後的答案,但是題目的n最大為100,m最大為10^9,那麼每個case的時間復雜度為O(Logm*n^3),當n最大為100的時候是會TLE的 5 我們發現初始的矩陣裡面,矩陣是一個循環同構的,就是說矩陣的每一行度能夠從上一行推出,那麼我們只要利用O(n^2)的時間求出第一行,然後我們在利用遞推求出剩下的n-1行,那麼總的時間復雜度為O(Logm*n^2) 代碼:
/************************************************
* By: chenguolin *
* Date: 2013-08-30 *
* Address: http://blog.csdn.net/chenguolinblog *
************************************************/
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef __int64 int64;
const int N = 110;
int arr[N];
int n , m , L , R , MOD;
struct Matrix{
int64 mat[N][N];
Matrix operator*(const Matrix& ma)const{
Matrix tmp;
for(int i = 0 ; i < n ; i++){
tmp.mat[0][i] = 0;
for(int j = 0 ; j < n ; j++)
tmp.mat[0][i] += mat[0][j]*ma.mat[j][i]%MOD;
tmp.mat[0][i] %= MOD;
}
for(int i = 1 ; i < n ; i++)
for(int j = 0 ; j < n ; j++)
tmp.mat[i][j] = tmp.mat[i-1][(j-1+n)%n];
return tmp;
}
};
void init(Matrix &ma){
memset(ma.mat , 0 , sizeof(ma.mat));
ma.mat[0][1] = L ; ma.mat[0][n-1] = R;
ma.mat[n-1][0] = L ; ma.mat[n-1][n-2] = R;
ma.mat[0][0] = ma.mat[n-1][n-1] = 1;
for(int i = 1 ; i < n-1 ; i++){
ma.mat[i][i-1] = R;
ma.mat[i][i+1] = L;
ma.mat[i][i] = 1;
}
}
void Pow(Matrix &ma){
Matrix ans;
memset(ans.mat , 0 , sizeof(ans.mat));
for(int i = 0 ; i < n ; i++)
ans.mat[i][i] = 1;
while(m){
if(m&1)
ans = ans*ma;
m >>= 1;
ma = ma*ma;
}
for(int i = 0 ; i < n ; i++){
int64 sum = 0;
for(int j = 0 ; j < n ; j++)
sum += ans.mat[i][j]*arr[j]%MOD;
if(i) printf(" ");
printf("%I64d" , sum%MOD);
}
puts("");
}
int main(){
int cas;
Matrix ma;
scanf("%d" , &cas);
while(cas--){
scanf("%d%d%d" , &n , &m , &L);
scanf("%d%d" , &R , &MOD);
for(int i = 0 ; i < n ; i++)
scanf("%d" , &arr[i]);
init(ma);
Pow(ma);
}
return 0;
}