题目链接:http://acm.fzu.edu.cn/problem.php?pid=1692
题意:n个小孩围城一圈,开始每个人有ai个苹果。接下来进行m轮分苹果。第t个人第i轮分得的苹果为R*x+L*y+z。x为第t左边的人上一次的苹果数,y为第t个人右边的人上一次的苹果数,z为第t个人本身拥有的苹果数。求m轮后每个人的苹果数。
思路:利用循环性,每次矩阵乘法的复杂度为O(n^2)。下面是一组测试数据计算初始矩阵(第一个矩阵)的1,2,3,4,5次方后的矩阵:
1 3 0 0 4
4 1 3 0 0
0 4 1 3 0
0 0 4 1 3
3 0 0 4 1
25 6 9 16 8
8 25 6 9 16
16 8 25 6 9
9 16 8 25 6
6 9 16 8 25
73 117 91 75 156
156 73 117 91 75
75 156 73 117 91
91 75 156 73 117
117 91 75 156 73
1009 700 742 972 673
673 1009 700 742 972
972 673 1009 700 742
742 972 673 1009 700
700 742 972 673 1009
int n,mod;
class Matrix
{
public:
int a[N][N];
void init(int x)
{
int i;
if(!x) clr(a,0);
else
{
clr(a,0);
FOR0(i,N) a[i][i]=1;
}
}
Matrix operator*(Matrix b)
{
int i,j,k,t;
Matrix p;
p.init(0);
FOR0(i,n) FOR0(k,n)
{
(p.a[0][i]+=(i64)a[0][k]*b.a[k][i]%mod)%=mod;
}
FOR1(i,n-1) FOR0(j,n)
{
p.a[i][j]=p.a[i-1][(j+n-1)%n];
}
return p;
}
Matrix power(int t)
{
Matrix ans,p=*this;
ans.init(1);
while(t)
{
if(t&1) ans=ans*p;
p=p*p;
t>>=1;
}
return ans;
}
void print()
{
int i,j;
FOR0(i,n)
{
FOR0(j,n) printf("%d ",a[i][j]);
puts("");
}
}
};
Matrix a;
int m,L,R;
int data[N];
int main()
{
rush()
{
RD(n,m);
RD(L,R,mod);
int i,l,r;
a.init(1);
FOR0(i,n)
{
l=(i+1)%n;
r=(i+n-1)%n;
a.a[i][i]=1;
a.a[i][l]+=L%mod;
a.a[i][r]+=R%mod;
}
a=a.power(m);
FOR0(i,n) RD(data[i]);
i64 ans,j;
FOR0(i,n)
{
ans=0;
FOR0(j,n) (ans+=(i64)a.a[i][j]*data[j]%mod)%=mod;
printf("%d",ans);
if(i<n-1) putchar(' ');
}
puts("");
}
return 0;
}