矩阵乘
来源:互联网 发布:洛阳聚麟网络怎么样 编辑:程序博客网 时间:2024/04/26 16:00
一年前这个时候学的矩阵乘法, 但是当时好像就没怎么懂, 前天碰到了这种题果然还是不会做, ,,多做几道练习吧。
求K位的相邻两位之差不大于2的题。
#include <iostream>#include <cstdio>#include <algorithm>#include <cmath>#include <cstring>#define mod 1000000007using namespace std;long long k;inline void cheng(int a[11][11], int b[11][11]){ int c[11][11] = {0}; for(int i = 0; i < 10; i ++) for(int j = 0; j < 10; j ++) for(int k = 0; k < 10; k ++) c[i][j] = ((long long)a[i][k] * b[k][j] + c[i][j]) % mod; for(int i = 0; i < 10; i ++) for(int j = 0; j < 10; j ++) a[i][j] = c[i][j]; }int a[11][11], b[11][11], ans;int main(){ freopen("sam.in", "r", stdin); freopen("sam.out", "w", stdout); scanf("%I64d", &k); long long n = k; if(n == 1){puts("10"); return 0;} for(int i = 0; i < 10; i ++)a[i][i] = 1; for(int i = 0; i < 10; i ++){ for(int j = 0; j < 10; j ++) if(abs(j - i) <= 2) b[i][j] = 1; } n--; while(n){ if(n & 1)cheng(a, b); n = n >> 1; cheng(b, b); } for(int j = 1; j < 10; j ++) for(int k = 0; k < 10; k ++) ans= (ans + a[k][j]) % mod; cout<<ans<<endl; // system("pause"); return 0;}然后做了noi2012随机数生成器
这个只是一个简单的两位的矩阵但是两个longlong乘起来会爆, 所以还需要用快速乘, 以前没写过快速乘, 不过还是很好写的, 就是和快速幂一样的思想, 从乘2到乘4再到乘8这样注意地把一个乘数分解就好了。但是我做这道题的时候还是不能自己构建出矩阵。。继续联系吧
#include <iostream>#include <cstdio>#include <algorithm>#include <cmath>#include <cstring>using namespace std;long long m, a, c, x0, n, q;long long cheng1(long long x, long long y){ long long ans = 0; for(; y; y>>=1, x = (x * 2) % m) if(y & 1) ans = (ans + x) % m; return ans;}inline void cheng(long long aa[5][5], long long bb[5][5]){ long long cc[5][5] = {0}; cc[1][1] = (cheng1(aa[1][1] , bb[1][1]) + cheng1(aa[1][2] , bb[2][1]))%m ; cc[1][2] = (cheng1(aa[1][1] , bb[1][2]) + cheng1(aa[1][2] , bb[2][2]))%m ; cc[2][1] = (cheng1(aa[2][1] , bb[1][1]) + cheng1(aa[2][2] , bb[2][1]))%m ; cc[2][2] = (cheng1(aa[2][1] , bb[1][2]) + cheng1(aa[2][2] , bb[2][2]))%m ; aa[1][1] = cc[1][1]; aa[1][2] = cc[1][2]; aa[2][1] = cc[2][1]; aa[2][2] = cc[2][2];}long long aa[5][5], bb[5][5];int main(){ scanf("%lld%lld%lld%lld%lld%lld", &m, &a, &c, &x0, &n, &q); aa[1][1] = c; aa[1][2] = x0; bb[1][1] = 1; bb[1][2] = 1;bb[2][2] = a; for(; n; n>>=1, cheng(bb, bb)) if(n & 1)cheng(aa, bb); printf("%lld\n", aa[1][2] % q); // system("pause"); return 0;}
对了lc 讲课的时候说到了一个很简单但是很好用的技巧
就是在
for(int i = 0; i < 10; i ++) for(int j = 0; j < 10; j ++) for(int k = 0; k < 10; k ++)这个循环中写成这样:
for(int i = 0; i < 10; i ++) for(int k = 0; k < 10; k ++)if(a[i][k]) for(int j = 0; j < 10; j ++)
就可以一下子快很多了!!!!!
这篇 写构造矩阵的文章真的觉得挺好的。
然后要做一下 这个 M67 的矩阵十题练下手吧。
关于题解M67 已经写得很详细了。
关于我总是弄错的一个点旋转之后的坐标, 可以 见此 , 有一个简单的证明。就是用一个和角公式, 挺简单的。
然后这道题就没什么了。
丑恶代码
#include <iostream>#include <cstdio>#include <algorithm>#include <cmath>#include <cstring>#define A alter.a#define pi 3.141592653589793238452643383279502884197169using namespace std;int n, m;struct Matrix{ double a[5][5]; }point[10005], alter, now, ans;Matrix cheng(Matrix x, Matrix y){ Matrix tmp; memset(tmp.a, 0, sizeof(tmp.a)); for(int i = 1; i <= 3; i ++) for(int k = 1; k <= 3; k ++)if(x.a[i][k]) for(int j = 1; j <= 3; j ++) tmp.a[i][j] += x.a[i][k] * y.a[k][j]; return tmp; }int main(){ scanf("%d%d", &n, &m); for(int i = 1; i <= n; i ++)scanf("%lf%lf", &point[i].a[1][1], &point[i].a[2][1]), point[i].a[3][1] = 1; memset(now.a, 0, sizeof(now.a)); for(int i = 1; i <= 3; i ++)now.a[i][i] = 1; for(int i = 1; i <= m; i ++){ char c[5]; scanf("%s", c); double a, b; memset(A, 0, sizeof(A)); for(int j = 1; j <= 3; j ++)A[j][j] = 1; if(c[0] == 'M'){ scanf("%lf%lf", &a, &b); A[1][3] = a; A[2][3] = b; } if(c[0] == 'X') A[2][2] = -1; if(c[0] == 'Y') A[1][1] = -1; if(c[0] == 'S'){ scanf("%lf", &a); A[1][1] = A[2][2] = a; } if(c[0] == 'R'){ scanf("%lf", &a); a = a / 180 * pi; A[1][1] = A[2][2] = cos(a); A[1][2] = -sin(a); A[2][1] = sin(a); } now = cheng(alter, now); } for(int i = 1; i <= n; i ++){ ans = cheng(now, point[i]); printf("%.1lf %.1lf\n", ans.a[1][1], ans.a[2][1]); } // system("pause"); return 0;}
hdu 1575
裸的矩阵快速幂, 以前打过的。
#include <iostream>#include <cstdio>#include <algorithm>#include <cmath>#include <cstring>#define mod 9973using namespace std;int n, k;struct Matrix{ int a[11][11]; }now, a, tmp;Matrix cheng(Matrix a, Matrix b){ memset(tmp.a, 0, sizeof(tmp.a)); for(int i = 1; i <= n; i ++) for(int k = 1; k <= n; k ++)if(a.a[i][k]) for(int j = 1; j <= n; j ++){ tmp.a[i][j] += (a.a[i][k] * b.a[k][j]) % mod; tmp.a[i][j] %= mod; } return tmp;}void quick(int k){ memset(now.a, 0, sizeof(now.a)); for(int i = 1; i <= n; i ++) now.a[i][i] = 1; while(k){ if(k & 1)now = cheng(now, a); k >>= 1; a = cheng(a, a); } }int main(){ int t; scanf("%d", &t); while(t --){ scanf("%d%d", &n, &k); for(int i = 1; i <= n; i ++) for(int j = 1; j <= n; j ++) scanf("%d", &a.a[i][j]); quick(k); int sum = 0; for(int i = 1; i <= n; i ++) sum += now.a[i][i];cout<<sum % mod<<endl; } // system("pause"); return 0;}
poj 3233
////////////////别人写的////////////////////
题目大意:给定矩阵A,求A + A^2 + A^3 + ... + A^k的结果(两个矩阵相加就是对应位置分别相加)。输出的数据mod m。k<=10^9。
这道题两次二分,相当经典。首先我们知道,A^i可以二分求出。然后我们需要对整个题目的数据规模k进行二分。比如,当k=6时,有:
A + A^2 + A^3 + A^4 + A^5 + A^6 =(A + A^2 + A^3) + A^3*(A + A^2 + A^3)
应用这个式子后,规模k减小了一半。我们二分求出A^3后再递归地计算A + A^2 + A^3,即可得到原问题的答案。
奇数: F[n]=F[n-1]+A^n
偶数: F[n]=F[n/2]+F[n/2]*An/2
算法: 二分+矩阵快速幂
/////////////////////////////////////////////////////很机智的题~~~~
#include <iostream>#include <cstdio>#include <algorithm>#include <cmath>#include <cstring>int mod;using namespace std;int n, k;struct Matrix{ int a[31][31]; }now, a, tmp, ans;Matrix cheng(Matrix a, Matrix b){ memset(tmp.a, 0, sizeof(tmp.a)); for(int i = 1; i <= n; i ++) for(int k = 1; k <= n; k ++)if(a.a[i][k]) for(int j = 1; j <= n; j ++){ tmp.a[i][j] += (a.a[i][k] * b.a[k][j]) % mod; tmp.a[i][j] %= mod; } return tmp;}Matrix jia(Matrix a, Matrix b){ for(int i = 1; i <= n; i ++) for(int j = 1; j <= n; j ++) tmp.a[i][j] = (a.a[i][j] + b.a[i][j]) % mod; return tmp; }Matrix quick(Matrix a, int k){ memset(now.a, 0, sizeof(now.a)); for(int i = 1; i <= n; i ++) now.a[i][i] = 1; while(k){ if(k & 1)now = cheng(now, a); k >>= 1; a = cheng(a, a); } return now;}Matrix work(int k){ if(k <= 1)return a; if(k % 2)return jia(work(k - 1), quick(a, k)); Matrix bb = work(k>>1); Matrix cc = quick(a, k>>1); cc = cheng(cc, bb); return jia(cc, bb); }int main(){ scanf("%d%d%d", &n, &k, &mod); for(int i = 1; i <= n; i ++) for(int j = 1; j <= n; j ++) scanf("%d", &a.a[i][j]); ans = work(k); for(int i = 1; i <= n; i ++){ for(int j = 1; j <= n; j ++)printf("%d ", ans.a[i][j]);cout<<endl; } // system("pause"); return 0;}
剩下还有几道都要写完!
- 矩阵乘
- 矩阵乘
- cache block 矩阵矩阵乘
- 矩阵连乘
- Strassen矩阵连乘
- 矩阵连乘问题
- 矩阵连乘问题
- 矩阵连乘
- 矩阵连乘
- 矩阵连乘
- 矩阵连乘
- 矩阵连乘问题
- 矩阵连乘问题
- 矩阵连乘问题
- 矩阵连乘问题
- 矩阵连乘问题
- DP---矩阵连乘
- 矩阵连乘 模版
- UVa 10878 ---- 求0.00ms解法
- ListView、ScrollView、GridView等去除滑动时边缘模糊
- git使用meld查看文件修改内容
- 最好的Layout_weight的讲解,从此释然
- 2014北京网络赛1007||hdu5038 模拟
- 矩阵乘
- 整数区间
- 小黑小波比.通过opacity实现淡化淡出
- hashelf算法测试 分布
- GridView指定列显示其他表求和后的数值
- ubuntu14.04下android开发环境的搭建5-4:eclipse+sdk的安装
- nginx---编译安装
- POJ 2578 Keep on Truckin'(水题)
- Java多线程之~~~Phaser重写onAdvance方法