矩阵基础1003 HDU 4965
2016-07-25 20:16
465 查看
题意:
给一个n*k的A矩阵和k*n的B矩阵(k<=6,n<=1000)
求(A*B)^(n*n),对于该矩阵的每个元素MOD6的和
思路:
一般方法在求幂的时候肯定会TLE
这里我们考虑拆分(A*B)^(n*n)
->(A*B)(A*B)^(n*n-2)(A*B)
->A*(B*A)^(n-1)*B 矩阵满足结合律
然后这样就可把A*B的1000*1000矩阵转化成6*6的矩阵
给一个n*k的A矩阵和k*n的B矩阵(k<=6,n<=1000)
求(A*B)^(n*n),对于该矩阵的每个元素MOD6的和
思路:
一般方法在求幂的时候肯定会TLE
这里我们考虑拆分(A*B)^(n*n)
->(A*B)(A*B)^(n*n-2)(A*B)
->A*(B*A)^(n-1)*B 矩阵满足结合律
然后这样就可把A*B的1000*1000矩阵转化成6*6的矩阵
#include<stdio.h> #include<string.h> #include<iostream> #include<algorithm> #include<math.h> #include<queue> #include<stack> #include<string> #include<vector> #include<map> #include<set> using namespace std; #define lowbit(x) (x&(-x)) typedef long long LL; const int maxn = 1005; const int inf=(1<<28)-1; #define Matrix_Size 7 const LL MOD = 6; int Size; struct Matrix { int mat[Matrix_Size][Matrix_Size]; void clear() { memset(mat,0,sizeof(mat)); } void output() { for(int i = 0;i < Size;i++) { for(int j = 0;j < Size;j++) printf("%d ",mat[i][j]); printf("\n"); } printf("\n"); } Matrix operator *(const Matrix &b)const { Matrix ret; for(int i = 0;i < Size;i++) for(int j = 0;j < Size;j++) { ret.mat[i][j] = 0; for(int k = 0;k < Size;k++) { long long tmp = (long long)mat[i][k]*b.mat[k][j]%MOD; ret.mat[i][j] = (ret.mat[i][j]+tmp); if(ret.mat[i][j]>=MOD) ret.mat[i][j] -= MOD; if(ret.mat[i][j]<0)//注意是否需要MOD ret.mat[i][j] += MOD; } } return ret; } }; Matrix pow_M(Matrix a,long long n) { Matrix ret; ret.clear(); for(int i = 0;i < Size;i++) ret.mat[i][i] = 1; Matrix tmp = a; while(n) { if(n&1)ret = ret*tmp; tmp = tmp*tmp; n>>=1; } return ret; } int A[maxn][7],B[7][maxn],At[maxn][7]; int main() { int n,k; while(~scanf("%d%d",&n,&k)&&!(n==0&&k==0)) { Size=k; 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]); Matrix C; C.clear(); for(int i=0;i<k;++i) for(int j=0;j<k;++j) { for(int s=0;s<n;++s) { C.mat[i][j]+=B[i][s]*A[s][j]; } } //C.output(); C=pow_M(C,n*n-1); //C.output(); memset(At,0,sizeof(At)); for(int i=0;i<n;++i) { for(int j=0;j<k;++j) { for(int s=0;s<k;++s) { At[i][j]=(At[i][j]+A[i][s]*C.mat[s][j])%MOD; } } } /*for(int i=0;i<n;++i) { for(int j=0;j<k;++j) printf("%lld ",At[i][j]); printf("\n"); } printf("\n");*/ LL Ans=0; for(int i=0;i<n;++i) { for(int j=0;j<n;++j) { LL tmp=0; for(int s=0;s<k;++s) { tmp=(tmp+At[i][s]*B[s][j])%MOD; } ///printf("%d ",tmp); Ans+=tmp; } //printf("\n"); } printf("%lld\n",Ans); } return 0; } /* 题意: 给一个n*k的A矩阵和k*n的B矩阵(k<=6,n<=1000) 求(A*B)^(n*n),对于该矩阵的每个元素MOD6的和 思路: 一般方法在求幂的时候肯定会TLE 这里我们考虑拆分(A*B)^(n*n) ->(A*B)*(A*B)^(n*n-2)*(A*B) ->A*(B*A)^(n-1)*B 矩阵满足结合律 然后这样就可把A*B的1000*1000矩阵转化成6*6的矩阵 */ #include<stdio.h> #include<string.h> #include<iostream> #include<algorithm> #include<math.h> #include<queue> #include<stack> #include<string> #include<vector> #include<map> #include<set> using namespace std; #define lowbit(x) (x&(-x)) typedef long long LL; const int maxn = 1005; const int inf=(1<<28)-1; #define Matrix_Size 7 const LL MOD = 6; int Size; struct Matrix { int mat[Matrix_Size][Matrix_Size]; void clear() { memset(mat,0,sizeof(mat)); } void output() { for(int i = 0;i < Size;i++) { for(int j = 0;j < Size;j++) printf("%d ",mat[i][j]); printf("\n"); } printf("\n"); } Matrix operator *(const Matrix &b)const { Matrix ret; for(int i = 0;i < Size;i++) for(int j = 0;j < Size;j++) { ret.mat[i][j] = 0; for(int k = 0;k < Size;k++) { long long tmp = (long long)mat[i][k]*b.mat[k][j]%MOD; ret.mat[i][j] = (ret.mat[i][j]+tmp); if(ret.mat[i][j]>MOD) ret.mat[i][j] -= MOD; if(ret.mat[i][j]<0)//注意是否需要MOD ret.mat[i][j] += MOD; } } return ret; } }; Matrix pow_M(Matrix a,long long n) { Matrix ret; ret.clear(); for(int i = 0;i < Size;i++) ret.mat[i][i] = 1; Matrix tmp = a; while(n) { if(n&1)ret = ret*tmp; tmp = tmp*tmp; n>>=1; } return ret; } int A[maxn][7],B[7][maxn],At[maxn][7]; int main() { int n,k; while(~scanf("%d%d",&n,&k)&&!(n==0&&k==0)) { Size=k; 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]); Matrix C; C.clear(); for(int i=0;i<k;++i) for(int j=0;j<k;++j) { for(int s=0;s<n;++s) { C.mat[i][j]+=B[i][s]*A[s][j]; } } //C.output(); C=pow_M(C,n*n-1); //C.output(); memset(At,0,sizeof(At)); for(int i=0;i<n;++i) { for(int j=0;j<k;++j) { for(int s=0;s<k;++s) { At[i][j]=(At[i][j]+A[i][s]*C.mat[s][j])%MOD; } } } /*for(int i=0;i<n;++i) { for(int j=0;j<k;++j) printf("%lld ",At[i][j]); printf("\n"); } printf("\n");*/ LL Ans=0; for(int i=0;i<n;++i) { for(int j=0;j<n;++j) { LL tmp=0; for(int s=0;s<k;++s) { tmp=(tmp+At[i][s]*B[s][j])%MOD; } ///printf("%d ",tmp); Ans+=tmp; } //printf("\n"); } printf("%lld\n",Ans); } return 0; }
相关文章推荐
- mysql的安装和用户权限
- OpenGL,z值转深度值计算
- 矩阵基础1002 CodeForces 450B
- 【Maven用户手册】Maven生命周期
- 矩阵基础1001 HDU 4990
- 计算几何 ( 凸包 )——Wall ( HDU 1248 )
- Linux动态链接库的创建与使用
- 操作各个版本的excel的链接写法
- Scala命令设置JVM参数的规则
- HDU 1254 推箱子(双层BFS)
- Android Studio中Android应用程序签名打包方法
- screen命令的详解
- HDU1335 POJ1546 UVA389 UVALive5306 ZOJ1334 Basically Speaking【进制+atio+itoa】
- mysql左链接,右链接,内部链接,交叉连接
- 【Maven用户手册】Maven是什么
- malloc、calloc、realloc的使用和区别
- 引入layoutlib.jar
- java泛型详解【转】
- linux入门之文本处理工具sed粗略使用(1)
- 数论基础1013 POJ 2478