POJ3233 Matrix Power Series
题意:
求
∑i=1nAi
(k<=109)
思路
大神Cai曾出过一道类似的,不过那个还更难;
框架就是二分加快速幂
对于
∑i=1nAi
我们可以将该式分解为A=
∑i=1n/2Ai
,观察到只需要将A式乘上一个
Ab/2
,那么就可以得到B=
∑i=n/2+1nAi+b/2
,原式=A+B;
如果n是个偶数,那么A+B就可以了,如果n是个奇数,那么可以换一个东西(迷)
A=
∑i=1n/2Ai
,B=
A(n+1)/2
,那么将A*B得到C=
∑i=(b+1)/2+1nAi+(b+1)/2
,那么原式还差一个
A(n+1)/2
,所以加上凑好项了:
∑i=1nAi=∑i=1n/2Ai+∑i=(b+1)/2+1nAi+(b+1)/2+A(n+1)/2=A+B+C
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
#define Rep(i,s,t) for(int i=s;i<=t;i++)
struct Mat{
int m[31][31];
};
Mat a,init;
int n,k,MOD;
Mat Mul(Mat A,Mat B)
{
Mat c;
memset(c.m,0,sizeof c.m);
Rep(i,1,n) Rep(j,1,n) Rep(k,1,n)
c.m[i][j]=(c.m[i][j]+A.m[i][k]*B.m[k][j])%MOD;
return c;
}
Mat Add(Mat A,Mat B)
{
Mat c;
memset(c.m,0,sizeof c.m);
Rep(i,1,n) Rep(j,1,n)
c.m[i][j]=(A.m[i][j]+B.m[i][j])%MOD;
return c;
}
Mat pow(Mat A,int k)
{
Mat ans=A,p=A;
k--;
while(k)
{
if(k & 1) ans=Mul(ans,p);
p=Mul(p,p);
k>>=1;
}
return ans;
}
Mat Sum(Mat A,int k)
{
if(k==1) return a;
Mat C=Sum(A,k>>1);
if(k & 1) {
Mat K=pow(A,(k>>1)+1);
C=Add(Mul(C,K),Add(C,K));
}
else {
Mat K=pow(A,k>>1);
C=Add(Mul(C,K),C);
}
return C;
}
int main()
{
while(scanf("%d%d%d",&n,&k,&MOD)!=EOF)
{
memset(a.m,0,sizeof a.m);
Rep(i,1,n) Rep(j,1,n) {scanf("%d",&a.m[i][j]);init.m[i][j]=(i==j);}
a=Sum(a,k);
Rep(i,1,n) {Rep(j,1,n-1) printf("%d ",a.m[i][j]);printf("%d\n",a.m[i][n]);}
}
return 0;
}