【题目链接】​​点击打开FZU 1692​

【题意】:1 题目的意思是有n个人构成一个圈,每个人初始的有ai个苹果,现在做m次的游戏,每一次游戏过后第i个人能够增加R*A(i+n-1)%n+L*A(i+1)%n 个苹果(题目有错),问m轮游戏过后每个人的苹果数

【思路】:


根据题目的意思我们能够列出一轮过后每个人的苹果数

   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)

代码:

/*
Problem id. FZU 1692
RunID: 631373
UserID: ACM_herongwei
Submit time: 2015-09-04 11:58:16
Language: C++
Length: 1806 Bytes.
Result: Accepted
*/

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
using namespace std;

typedef long long LL;
const int N=105;

int arr[N];
int n,m,L,R,MOD;

struct mut
{
LL mat[N][N];
mut()
{
memset(mat,0,sizeof(mat));
}
void init()
{
for(int i=0; i<n; ++i)
{
mat[i][(i+n-1)%n]=L;
mat[i][i]=1;
mat[i][(i+1)%n]=R;
}
}
};

mut multi(mut &a,mut &b)
{
mut c;
for(int i=0; i<n; ++i)
{
if(a.mat[0][i])
{
for(int j=0; j<n; ++j)
{
if(b.mat[i][j])
{
c.mat[0][j]=(c.mat[0][j]+a.mat[0][i]*b.mat[i][j])%MOD;
}
}
}
}
for(int i = 1; i < n; i ++)
{
c.mat[i][0] = c.mat[i - 1][n - 1];
for(int j = 1; j <n; j ++)
c.mat[i][j] = c.mat[i - 1][j - 1];
}

return c;
}
mut poww(mut unit, mut a,int n)
{
while(n)
{
if(n&1) unit=multi(unit,a);
a=multi(a,a);
n>>=1;
}
return unit;
}

void solve()
{
int ans=0;
mut unit,a;
scanf("%d %d %d %d %d",&n,&m,&R,&L,&MOD);
for(int i=0; i<n; ++i)
{
scanf("%d",&arr[i]);
unit.mat[i][i]=1;
}
a.init();
unit=poww(unit,a,m);
for(int i=0; i<n; ++i)
{
ans=0;
for(int j=0; j<n; ++j)
{
if(unit.mat[i][j]&&arr[j])
ans+=(unit.mat[i][j]*arr[j])%MOD;
}
if(i) printf(" ");
printf("%d",ans%MOD);
}
puts("");
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
solve();
}
return 0;
}