矩阵快速幂专题
占坑---------
-----填坑------
vj开的专题 密码1234589
数论_矩阵
题意:f1=x,f2=y,fi=fi-1+fi+1,输入x,y,和n,求fn%1e9+7
思路:fi=fi-1+fi+1,fi+1=fi+fi+2,俩式相加得 fi+2=-fi-1,矩阵快速幂
AC代码:
#include "iostream" #include "string.h" #include "stack" #include "queue" #include "string" #include "vector" #include "set" #include "map" #include "algorithm" #include "stdio.h" #include "math.h" #define ll long long #define lson l,mid,rt<<1 #define rson mid+1,r,rt<<1|1 #define mem(a) memset(a,0,sizeof(a)) using namespace std; const int N=2; const ll mod=1e9+7; struct Mat{ ll m[N][N]; Mat(){ mem(m); } Mat friend operator* (Mat a, Mat b){ Mat c; for(int i=0; i<N; i++) for(int j=0; j<N; j++) for(int k=0; k<N; k++) c.m[i][j]=(c.m[i][j]+a.m[i][k]*b.m[k][j])%mod; return c; } }; Mat PowMod(Mat a, ll b){ Mat c; for(int i=0; i<N; ++i) c.m[i][i]=1; while(b){ if(b&1) c=c*a; a=a*a; b>>=1; } return c; } int main(){ ll aa[10],n; while(scanf("%I64d%I64d%I64d",&aa[1],&aa[2],&n)!=EOF){ Mat a,s; a.m[0][0]=aa[2],a.m[0][1]=-aa[1]; s.m[0][0]=1,s.m[1][0]=1,s.m[0][1]=-1; a=a*PowMod(s,n-2>0?n-2:0); printf("%I64d\n",n-2>0?(a.m[0][0]+mod)%mod:(aa[n]+mod)%mod); } return 0; }
题意:给你一个k,n,接下来是一个n*k的矩阵A,和k*n的矩阵B,矩阵A*B得到矩阵C,求C^n*n矩阵里面所有元素的和
思路:如果不做处理直接矩阵快速幂,N^3lgN的时间复杂度肯定吃不消,但是这里n很大,k很小,A*B 是n*n矩阵,B*A就是K*K的矩阵,所以写成A*(B*A)^n*n-1*B 就可以了
AC代码:
#include "iostream" #include "string.h" #include "stack" #include "queue" #include "string" #include "vector" #include "set" #include "map" #include "algorithm" #include "stdio.h" #include "math.h" #define ll long long #define mem(a) memset(a,0,sizeof(a)) using namespace std; const int mod=6; const int N=6; struct Mat{ int m[N][N]; Mat(){ mem(m); } friend Mat operator* (Mat a, Mat b){ Mat c; for(int i=0; i<N; ++i) for(int j=0; j<N; ++j) for(int k=0; k<N; ++k) c.m[i][j]=(c.m[i][j]+a.m[i][k]*b.m[k][j])%mod; return c; } }; Mat PowMod(Mat s, int b){ Mat ans; for(int i=0; i<N; ++i) ans.m[i][i]=1; while(b){ if(b&1) ans=ans*s; s=s*s; b>>=1; } return ans; } int c[1005][10],d[1005][1005]; int main() { int n,k; while(scanf("%d%d",&n,&k)&&(n||k)){ Mat s; mem(c),mem(d); int a[1005][10],b[10][1005]; for(int i=0; i<n; ++i) for(int j=0; j<k; ++j) scanf("%d",&a[i][j]); for(int i=0; i<k; ++i) for(int j=0; j<n; ++j) scanf("%d",&b[i][j]); for(int i=0; i<k; ++i) for(int j=0; j<k; ++j) for(int l=0; l<n; ++l) s.m[i][j]=(s.m[i][j]+b[i][l]*a[l][j])%mod; s=PowMod(s,n*n-1); //for(int i=0; i<k; ++i){for(int j=0; j<k; ++j) cout<<s.m[i][j]<<" ";cout<<endl;} for(int i=0; i<n; ++i) for(int j=0; j<k; ++j) for(int l=0; l<k; ++l) c[i][j]=(c[i][j]+a[i][l]*s.m[l][j])%mod; int sum=0; for(int i=0; i<n; ++i) for(int j=0; j<n; ++j) for(int l=0; l<k; ++l) d[i][j]=(d[i][j]+c[i][l]*b[l][j])%mod; for(int i=0; i<n; ++i) for(int j=0; j<n; ++j) sum+=d[i][j]; printf("%d\n",sum); } return 0; }