矩阵快速幂+二分求前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; }
原文地址:http://blog.csdn.net/u011041349/article/details/39188603