Matrix Power Series
Time Limit: 3000MS | Memory Limit: 131072K | |
Total Submissions: 26191 | Accepted: 10773 |
Description
Given a n × n matrix A and a positive integer k, find the sum S = A + A2 + A3 + … + Ak.
Input
The input contains exactly one test case. The first line of input contains three positive integers n (n ≤ 30), k (k ≤ 109) and m (m < 104). Then follow n lines each containing n nonnegative integers below 32,768, giving A’s elements in row-major order.
Output
Output the elements of S modulo m in the same way as A is given.
Sample Input
2 2 4 0 1 1 1
Sample Output
1 2 2 3
思路:因为S=A+A^2+A^3+...+A^K。但是K有1e9那么多。直接写肯定不行,然后我就想到要用每次提取出来一个A,然后递归回去算S,然后1e9还是不行,最后我推K=4的情况,S可以写成S=A+A^2+A^2(A+A^2)。而K=5时,S=A+A^2+A^3+A^3(A+A^2)。然后我发现每次都是那这个k分一半向下推,最后开递归回来求出来S即可。**疼的是写的时候忘了矩阵快速幂的重载*来实现矩阵相乘,然后就老老实实的打了函数。手残把奇数的情况打错了,比赛后1分钟才找打bug,然后就A了
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<queue>
#include<algorithm>
#include<iostream>
#include<map>
#define inf 0x3f3f3f3f
#define ll long long
#define maxx 5000000
using namespace std;
int n,k,m;
struct node
{
int x[40][40];
}st;
node mul(node a,node b)
{
node c;
memset(c.x,0,sizeof(c.x));
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
for(int k=1;k<=n;k++)
c.x[i][j]=(c.x[i][j]+a.x[i][k]*b.x[k][j])%m;
return c;
}
node pow(int u,node s)
{
node c;
memset(c.x,0,sizeof(c.x));
for(int i=1;i<=n;i++)
c.x[i][i]=1;
while(u)
{
if(u%2==1)
c=mul(c,s);
u=u/2;
s=mul(s,s);
}
return c;
}
node add(node a,node b)
{
node temp;
memset(temp.x,0,sizeof(temp.x));
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
temp.x[i][j]=(a.x[i][j]+b.x[i][j])%m;
}
}
return temp;
}
node sum(node ans,int kk)
{
node temp,res;
if(kk==1)
return ans;
temp=sum(ans,kk/2);
if(kk%2==0)
{
res=pow(kk/2,ans);
return add(mul(res,temp),temp);
}
else
{
res=pow(kk/2+1,ans);
temp=add(mul(res,temp),temp);
return add(temp,res);
}
}
int main()
{
scanf("%d%d%d",&n,&k,&m);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
scanf("%d",&st.x[i][j]);
node ans=sum(st,k);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if(j!=1) printf(" ");
printf("%d",ans.x[i][j]%m);
}
printf("\n");
}
}