矩阵快速幂+二分求前n项和
矩阵快速幂是有模板的,多做几道题就会理解,前提是要会快速幂取模;
之所以用二分是因为求和的过程:A^1+A^2...+A^(k-1)+A^k, k是1e9的,所以暴力求和肯定会TLE,在网上找到
了二分求矩阵和的方法;
公式为 (1+A^(k/2))*(A+A^2+..+A^k/2) 的,所以可以写成二分递归,如果k为奇数的话,sum就加上A^k(k为当
前的k值,不再是最初的值),反正是个公式,你要不信的话可以证明一下,所以就贴代码了,感觉到姿势不够优美
呀。
#include <map>
#include <cmath>
#include <queue>
#include <vector>
#include <cstdio>
#include <string>
#include <cstring>
#include <iostream>
#include <algorithm>
#define maxn 50
#define ll long long
using namespace std;
int n,k,m;
struct Matrix
{
ll v[maxn][maxn];
} matrix;
Matrix Mul(Matrix u,Matrix uu)
{
Matrix c;
memset(c.v,0,sizeof(c.v));
for(int i=0; i<m; i++)
for(int j=0; j<m; j++)
{
for(int kk=0; kk<m; kk++)
c.v[i][j]+=u.v[i][kk]*uu.v[kk][j];
c.v[i][j]%=k;
}
return c;
}
Matrix tul(Matrix A,int t)
{
Matrix AA=A;
Matrix s;
memset(s.v,0,sizeof(s.v));
for(int i=0; i<m; i++) s.v[i][i]=1;
while(t)
{
if(t&1) s=Mul(s,AA);
t/=2;
AA=Mul(AA,AA);
}
return s;
}
Matrix pl(Matrix ff,Matrix fff)
{
for(int i=0; i<m; i++)
for(int j=0; j<m; j++)
{
ff.v[i][j]+=fff.v[i][j];
ff.v[i][j]%=k;
}
return ff;
}
Matrix sum(Matrix ff,int dd)
{
if(dd==1) return ff;
Matrix pp;
memset(pp.v,0,sizeof(pp.v));
for(int i=0; i<m; i++) pp.v[i][i]=1;
pp=pl(pp,tul(ff,dd>>1));
pp=Mul(pp,sum(ff,dd>>1));
if(dd&1) pp=pl(pp,tul(ff,dd));
return pp;
}
int main()
{
scanf("%d%d%d",&m,&n,&k);
for(int i=0; i<m; i++)
for(int j=0; j<m; j++)
scanf("%lld",&matrix.v[i][j]);
Matrix aa;
aa=sum(matrix,n);
for(int i=0; i<m; i++)
{
for(int j=0; j<m; j++)
printf("%lld ",aa.v[i][j]%k);
cout<<endl;
}
return 0;
}