(A个水题也要发一篇,是不是病了)
好吧来看题目,poj3233。
A+A^2+A^3+......
前几天才看到这个求级数的方法,今天就用上了。
设work(A,n)=A+A^2+A^3+.....A^n
当n为偶数,work(A,n)=A+A^2+A^3+.....A^n=A+A^2+A^3+.....A^n/2+(A^n/2)*(A+A^2+A^3+.....A^n/2)=work(A,n/2)*(A^n/2+E);
n为奇数work(A,n)=work(A,n-1)+A^n;
跑得很慢的代码:
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
#define Max_n 34
int n,k,m;
struct mat{
int s[Max_n][Max_n];
//int operator[][](const int &a,const int &b){return s[a][b];}
mat operator *(const mat &b)const{
int i,j,k,tmp;
mat ret;
for(i=1;i<=n;++i){
for(j=1;j<=n;++j){
tmp=0;
for(k=1;k<=n;++k){
tmp=(tmp+(s[i][k]*b.s[k][j])%m)%m;
}
//printf(" %d %d\n",tmp,m);
ret.s[i][j]=tmp;
}
}
return ret;
}
mat operator +(const mat &b)const{
int i,j;
mat ret;
for(i=1;i<=n;++i){
for(j=1;j<=n;++j){
ret.s[i][j]=(s[i][j]+b.s[i][j])%m;
}
}
return ret;
}
void inite(){
int i,j;
for(i=1;i<=n;++i)
for(j=1;j<=n;++j){
if (i==j) s[i][j]=1;else s[i][j]=0;
}
}
void print(){
int i,j;
for(i=1;i<=n;++i){
for(j=1;j<=n;++j){
printf("%d",s[i][j]);
if (j!=n) printf(" ");
}
printf("\n");
}
}
}a,ans;
mat smul(mat b,int t){
mat ret;
ret.inite();
while(t){
if (t&1){
ret=ret*b;
t=t^1;
}
else {
b=b*b;
t>>=1;
}
}
return ret;
}
mat work(mat c,int k){
mat E;
E.inite();
if (k==0) return E;
else if (k==1) return c;
if (k&1) return work(c,k-1)+smul(c,k);
else return work(c,k/2)*(smul(c,k/2)+E);
}
int main(){
//freopen("3233in.txt","r",stdin);
int i,j;
scanf("%d%d%d",&n,&k,&m);
for(i=1;i<=n;++i){
for(j=1;j<=n;++j){
scanf("%d",&a.s[i][j]);
a.s[i][j]%=m;
}
}
ans=work(a,k);
ans.print();
return 0;
}