POJ 3233 Matrix Power Series
题目链接:http://poj.org/problem?id=3233
运用两次二分,对Ak运用快速幂,对S用二分处理(求一个递归式)
题意:求 S=A+A2+A3+ … +Ak.
思路:AK首先想到矩阵快速幂。
1.当K为奇数时,如K=5时 sum(5)=A+A^2+A^3+A^4+A^5=A+A^2+A^3*(A+A^2)+A^3=sum(2)+A^3*sum(2)+A^3=sum(5/2)+A^(5/2+1)*sum(5/2)+A^(5/2+1)
所以sum(n)=sum(n/2)+A^(n/2+1)*sum(n/2)+A^(n/2+1)
2.当K为偶数时,如K=4时 sum(4)=A+A^2+A^3+A^4=A^2*(A+A^2)+A+A^2=A^2*sum(2)+sum(2)=A^(4/2)*sum(4/2)+sum(4/2);
所以sum(n)=A^(n/2)*sum(n/2)+sum(n/2);
#include<stdio.h>
#include<string.h>
struct Matrix
{
int m[40][40];
};
struct Matrix I,s;
int n,kmod;
Matrix Mul(Matrix a,Matrix b)
{
Matrix c;
int i,j,k;
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
{
c.m[i][j]=0;
for(k=0;k<n;k++)
{
c.m[i][j]+=(a.m[i][k]*b.m[k][j]);
c.m[i][j]%=kmod;
}
}
}
return c;
}
Matrix Add(Matrix a,Matrix b)
{
Matrix c;
int i,j;
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
{
c.m[i][j]=(a.m[i][j]+b.m[i][j]);
c.m[i][j]%=kmod;
}
}
return c;
}
Matrix Quickpow(Matrix a,int n)
{
Matrix m,b;
m=a,b=I;
while(n)
{
if(n%2)
b=Mul(b,m);
n/=2;
m=Mul(m,m);
}
return b;
}
Matrix Sum(int n)
{
Matrix ans,temp;
if(n==1)
return s;
temp=Sum(n/2);
if(n%2) //n为奇数时sum(n)=sum(n/2)+sum(n/2)*s^(n/2+1)+s^(n/2+1)
{
ans=Quickpow(s,(n/2)+1);
temp=Add(temp,Mul(temp,ans));
ans=Add(ans,temp);
}
else //n为偶数时sum(n)=sum(n/2)+sum(n/2)*s^(n/2)
{
ans=Quickpow(s,n/2);
ans=Add(temp,Mul(ans,temp));
}
return ans;
}
int main()
{
int i,j;
int k;
while(scanf("%d %d %d",&n,&k,&kmod)!=EOF)
{
memset(I.m,0,sizeof I.m);
for(i=0;i<n;i++)
I.m[i][i]=1;
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
{
scanf("%d",&s.m[i][j]);
}
}
Matrix ans;
ans=Sum(k);
for(i=0;i<n;i++)
{
for(j=0;j<n-1;j++)
{
printf("%d ",ans.m[i][j]);
}
printf("%d\n",ans.m[i][j]);
}
}
return 0;
}