NO.4 快速幂或者矩阵快速幂
来源:互联网 发布:录屏软件cs6 编辑:程序博客网 时间:2024/06/06 01:38
快速幂的算法函数:
int pow1(int a, int b){ int ans = 1; while(b) { if(b&1)//相当于b%2==1,位运算,判断二进制最后一位是否为奇数 ans *= a; a *= a; b >>= 1;//位运算,将二进制右移一位,相当于b /= 2; } return ans;}
快速幂取模:
int pow1(int a, int b, int c)//a的b次方,取模c{ int ans = 1; a = a % c;//积的取余等于取余的积的取余 while(b) { if(b & 1)//相当于b%2==1,位运算,判断二进制最后一位是否为奇数 ans = (ans * a) % c; a = (a * a) % c; b >>= 1;//位运算,将二进制右移一位,相当于b /= 2; } return ans;}
矩阵的快速幂:
#define MAXN 15#define MOD 10000007typedef long long int LL;LL res[MAXN][MAXN];int N;void M(LL a[MAXN][MAXN], LL b[MAXN][MAXN])//两个矩阵的相乘{ LL ans[MAXN][MAXN]; memset(ans, 0, sizeof(ans)); for(int i=0;i<N;i++) { for(int j=0;j<N;j++) { for(int k=0;k<N;k++) { ans[i][j] = (ans[i][j]+a[i][k]*b[k][j]%MOD)%MOD; } } } for(int i=0;i<N;i++) { for(int j=0;j<N;j++) { a[i][j] = ans[i][j]; } }}void K(LL a[MAXN][MAXN], int n )//矩阵的快速幂{ for(int i=0;i<N;i++) { for(int j=0;j<N;j++) { //相比数的快速幂,把1变成单位矩阵 res[i][j] = (i==j);//res是单位矩阵 } } while(n) { if(n&1) M(res, a); M(a, a); n >>= 1; }}
矩阵的快速幂:
高效计算矩阵的高次方。
简单的入门题目
think:
计算矩阵的高次方,然后取对角线之和。
#include <stdio.h>#include <string.h>#include <algorithm>int k, m;struct S{ int r,c; int a[15][15];};S ori,res;void init(){ memset(res.a,0,sizeof(res.a)); for(int i=1;i<=10;i++) res.a[i][i]=1; for(int i=2;i<=10;i++) for(int j=1;j<=10;j++) { if(i-1!=j) ori.a[i][j]=0; else ori.a[i][j]=1; }}S maxtri(S x,S y){ S z; memset(z.a,0,sizeof(z.a)); for(int i=1;i<=10;i++) { for(int k=1;k<=10;k++) { if(x.a[i][k]==0) continue; for(int j=1;j<=10;j++) z.a[i][j]=(z.a[i][j]+(x.a[i][k]*y.a[k][j])%m)%m; } } return z;}void maxtri_mod(int n){ while(n) { if(n&1) res=maxtri(res,ori); ori=maxtri(ori,ori); n>>=1; }}int main(){ while(scanf("%d%d",&k,&m)!=EOF) { for(int i=1;i<=10;i++) scanf("%d",&ori.a[1][i]); init(); if(k<=9) { printf("%d\n",k%m); continue; } maxtri_mod(k-9); int sum=0; for(int i=1;i<=10;i++) { sum+=(res.a[1][i]*(10-i))%m; sum%=m; } printf("%d\n",sum%m); } return 0;}
A - Jzzhu and Sequences
这算是一道矩阵快速幂的问题,不过有简单方法。
#include<stdio.h>int main(){ int x, m, y; int a[20]; scanf("%d %d", &x, &y); a[1]=x; a[2]=y; scanf("%d", &m); //观察发现,此题目有规律,每六组一循环 for(int i=3; i<=6; i++) { a[i] = a[i-1] - a[i-2]; } a[0] = a[6]; printf("%d\n", (((a[m%6]%1000000007)+1000000007)%1000000007));//可能有负数 return 0;}
B - 233 Matrix
#include <stdio.h>#include <stdlib.h>#include <string.h>#define MAXN 15#define MOD 10000007typedef long long int LL;LL res[MAXN][MAXN];int N;void M(LL a[MAXN][MAXN], LL b[MAXN][MAXN]){ LL ans[MAXN][MAXN]; memset(ans, 0, sizeof(ans)); for(int i=0;i<N;i++) { for(int j=0;j<N;j++) { for(int k=0;k<N;k++) { ans[i][j] = (ans[i][j]+a[i][k]*b[k][j]%MOD)%MOD; } } } for(int i=0;i<N;i++) { for(int j=0;j<N;j++) { a[i][j] = ans[i][j]; } }}void K(LL a[MAXN][MAXN], int n){ for(int i=0;i<N;i++) { for(int j=0;j<N;j++) { res[i][j] = (i==j); } } while(n) { if(n&1) M(res, a); M(a, a); n >>= 1; }}int main(){ int a, b; LL A[MAXN]; LL AA[MAXN][MAXN]; while(~scanf("%d %d", &a,&b)) { N = a + 2; A[0] = 23; A[a+1] = 3; memset(AA, 0, sizeof(AA)); for(int i=1;i<=a;i++) scanf("%lld", &A[i]); for(int i=0;i<N;i++) { if(i!=N-1) AA[i][0] = 10; for(int j=1;j<=i;j++) { if(i!=N-1) AA[i][j] = 1; } AA[i][N-1] = 1; } K(AA, b); LL ans = 0; for(int i=0;i<N;i++) { ans = (ans + A[i]*res[N-2][i]%MOD)%MOD; } printf("%lld\n", ans); } return 0;}
阅读全文
0 0
- NO.4 快速幂或者矩阵快速幂
- 快速幂或者矩阵快速幂
- 快速幂或者矩阵快速幂
- 快速矩阵快速幂
- 快速幂||矩阵快速幂
- 快速幂&矩阵快速幂
- 快速幂,矩阵快速幂
- 快速幂 矩阵快速幂
- 快速幂&矩阵快速幂
- 【快速幂】【矩阵快速幂】
- 快速幂和快速矩阵
- 快速乘/快速幂/矩阵快速幂
- 快速乘 快速幂 矩阵快速幂
- 快速幂,快速幂取模,矩阵快速幂
- 转移矩阵+矩阵快速幂
- 矩阵乘法 矩阵快速幂
- 构造矩阵+矩阵快速幂
- poj3070--矩阵 快速幂
- 多平台QT中文乱码问题解决办法
- Centos下配置vim自动补全
- HDU-2035-人见人爱A^B
- java冒泡排序算法
- div标签中的文字如何垂直居中
- NO.4 快速幂或者矩阵快速幂
- bash学习1 命令别名设置、显示当前目录、变量使用例子
- Linux运维进阶-文档总结-红帽企业版 集群(热备)套件
- STL学习之九:set和multiset用法示例
- 使用pageHelper快速构建分页
- HDU 3065 2017 Multi-University Training Contest
- 链表合并
- Spring里的Bean继承与Java继承的区别
- Python爬虫学习纪要(二):BeautifulSoup相关知识点2