一类常见的矩阵快速幂题型 总结
来源:互联网 发布:淘宝客服绩效管理 编辑:程序博客网 时间:2024/05/16 07:03
Googlecode jam 2008 Round 1A(c.Numbers)
【题意】计算的小数点前三位数,不足三位补0,正整数n的最大值为20亿。
【前提】:满足
的值在【0,1】范围
首先将
展开之后可以发现
的形式,同样的,有
因此,
是个整数,
其中
这正是解题的关键!
由于
所以的整数部分等于
根据以上的推导
只要高效的求出an就可以解决这个问题了
由于
为观察仔细,进一步展开得:
得出
的递推关系
因此,可以用矩阵表示这个递推关系,使用矩阵快速幂,在O(logn)的时间里求出和,由于此题只要取前3位,因此对1000取模就可以了
代码:
#include <stdio.h>#include <string.h>#include <iostream>#include <algorithm>using namespace std;typedef long long LL;const LL siz=2; // max size of the matrix,#define MODD(a,b) (((a%b)+b)%b)LL A,B,N,M,ret;struct mut{ LL mat[siz][siz]; mut(){ memset(mat,0,sizeof(mat)); } void init(LL a,LL b,LL c,LL d){ mat[0][0]=a; mat[0][1]=b; mat[1][0]=c; mat[1][1]=d; } mut operator *(const mut &c){ mut res; for(int i=0; i<siz; ++i){ for(int k=0; k<siz; ++k){ for(int j=0; j<siz; ++j){ res.mat[i][j]=MODD(res.mat[i][j]+mat[i][k]*c.mat[k][j],M); } } } return res; }} AC;mut poww(LL n){ mut ans; ans.init(1,0,0,1); while(n){ if(n&1) ans=ans*AC; n>>=1; AC=AC*AC; } return ans;}int main(){ int t; scanf("%d",&t); while(t--){ scanf("%lld",&N); M=1000; AC.init(3,5,1,3); mut ans=poww(N); printf("%03lld\n",MODD(2*ans.mat[0][0]-1,M)); } return 0;}
HDU 2256 Problem of Precision
【题意】:
【思路】和上题思路一样:
代码:
/* * Problem: HDU No.2256* Running time: 15MS * Complier: G++ * Author: javaherongwei * Create Time: 23:56 2015/9/21 星期一*/ #include <stdio.h>#include <string.h>#include <iostream>#include <algorithm>using namespace std;typedef long long LL;const LL siz=2; // max size of the matrix,#define MODD(a,b) (((a%b)+b)%b)LL A,B,N,M,ret;struct mut{ LL mat[siz][siz]; mut(){ memset(mat,0,sizeof(mat)); } void init(LL a,LL b,LL c,LL d){ mat[0][0]=a; mat[0][1]=b; mat[1][0]=c; mat[1][1]=d; } mut operator *(const mut &c){ mut res; for(int i=0; i<siz; ++i){ for(int k=0; k<siz; ++k){ for(int j=0; j<siz; ++j){ res.mat[i][j]=MODD(res.mat[i][j]+mat[i][k]*c.mat[k][j],M); } } } return res; }} AC;mut poww(LL n){ mut ans; ans.init(1,0,0,1); while(n){ if(n&1) ans=ans*AC; n>>=1; AC=AC*AC; } return ans;}int main(){ int t; scanf("%d",&t); while(t--){ scanf("%lld",&N); M=1024; AC.init(5,12,2,5); mut ans=poww(N); printf("%lld\n",MODD(2*ans.mat[0][0]-1,M)); } return 0;}
HDU 1575 Tr A
【题目链接】:click here~~
24K纯裸的矩阵计算:
【题意】:给定一个n*n的矩阵要求矩阵的k次幂之后的矩阵的对角线的和
代码:
/** Problem: HDU No.1575* Running time: 0MS* Complier: G++* Author: javaherongwei* Create Time: 8:10 2015/9/22 星期二*/#include <stdio.h>#include <string.h>#include <iostream>#include <algorithm>using namespace std;typedef long long LL;#define MODD(a,b) (((a%b)+b)%b)LL A,B,K,M,ret;LL N;LL siz; // max size of the matrix,struct mut{ LL mat[10][10]; mut(){ memset(mat,0,sizeof(mat)); } void init(){ for(int i=0; i<siz; ++i) for(int j=0; j<siz; ++j) if(i==j)mat[i][j]=1; else mat[i][j]=0; } mut operator *(const mut &c){ mut res; for(int i=0; i<siz; ++i){ for(int k=0; k<siz; ++k){ for(int j=0; j<siz; ++j){ res.mat[i][j]=MODD(res.mat[i][j]+mat[i][k]*c.mat[k][j],M); } } } return res; }} AC;mut poww(LL n){ mut ans; ans.init(); while(n){ if(n&1) ans=ans*AC; n>>=1; AC=AC*AC; } return ans;}int main(){ int t;scanf("%d",&t); while(t--){ scanf("%d %lld",&N,&K);M=9973;siz=N; for(int i=0; i<N; ++i){ for(int j=0; j<N; ++j) scanf("%d",&AC.mat[i][j]); } mut ans=poww(K); LL sum=0; for(int i=0; i<N; ++i){ sum+=ans.mat[i][i]; } printf("%lld\n",MODD(sum,M)); } return 0;}
CodeForces 185A Plant
【题目链接】
点击打开cf 185A
【思路】: 递推+矩阵快速幂
分析:
1 题目要求找到在n年后向上三角形的个数
2 写出前面的几个数F(0) = 1 , F(1) = 3 , F(2) = 10 , F(3) = 36 ,我们可以发现每一个向上三角形在后面形成的时候必然是分成了3个向上+1个向下的,总共分成了4个,这是包含了向下的,所以要减去,然后发现F(1向下)=1,F(2想下)=3-1=2,因此向下的可以推出关系:
从而找到通项公式 :
构造矩阵:
之后就是矩阵快速幂了
代码:
/** Problem: CodeForces 185A* Running time: 8MS* Complier: G++* Author: javaherongwei* Create Time: 9:10 2015/9/22 星期二*/#include <stdio.h>#include <string.h>#include <iostream>#include <algorithm>using namespace std;typedef long long LL;#define MODD(a,b) (((a%b)+b)%b)LL A,B,K,M,ret;LL N;const int siz=2; // max size of the matrix,struct mut{ LL mat[siz][siz]; mut(){ memset(mat,0,sizeof(mat)); } void init(LL a,LL b,LL c,LL d){ mat[0][0]=a;mat[0][1]=b; mat[1][0]=c;mat[1][1]=d; } mut operator *(const mut &c){ mut res; for(int i=0; i<siz; ++i){ for(int k=0; k<siz; ++k){ for(int j=0; j<siz; ++j){ res.mat[i][j]=MODD(res.mat[i][j]+mat[i][k]*c.mat[k][j],M); } } } return res; }} AC;mut poww(LL n){ mut ans; ans.init(1,0,0,1); while(n){ if(n&1) ans=ans*AC; n>>=1; AC=AC*AC; } return ans;}int main(){ //int t;scanf("%d",&t); // while(t--){ while(~scanf("%lld",&N)){ M=1e9+7; AC.init(4,-1,0,2); mut ans=poww(N); printf("%lld\n",MODD(ans.mat[0][0]*1+ans.mat[0][1]*1,M)); } return 0;}
HDU 2842 Chinese Rings
【题目链接】点击打开hdu2842
【思路】: 矩阵快速幂
【分析】:
1 题目的意思是给定n个环,和一些规则:
If the first k rings are all off and the (k + 1)th ring is on, then the (k + 2)th ring can be taken off or taken on with one step. (0 ≤ k ≤ 7)
要把所有的环全部拆下最少需要的步数
2 题目规定如果要拆第n个环,那么第n-1个要挂着,n-2环要被拆下。那么我们设f(n)表示拆下前n个环的最少的步骤
那么考虑第n个环的情况,第n-1个环必须要挂着,n-2环要拆下,那么这一步就要f(n-2),拆下第n个需要1步。然后只剩下第n-1个环,由于n-1环需要第n-2环挂着,所以我们需要把前n-2个环挂上去,所以需要f(n-2),剩下n-1个需要拆下需要f(n-1)。那么总的需要:
3 接下来利用矩阵快速幂即可
代码:
/** Problem: HDU 2842* Running time: 0MS* Complier: G++* Author: javaherongwei* Create Time: 9:10 2015/9/22 星期二*/#include <stdio.h>#include <string.h>#include <iostream>#include <algorithm>using namespace std;typedef long long LL;#define MODD(a,b) (((a%b)+b)%b)LL A,B,K,M,ret;LL N;const int siz=3; // max size of the matrix,struct mut{ LL mat[siz][siz]; mut(){ memset(mat,0,sizeof(mat)); } void init(LL a1,LL a2,LL a3,LL b1,LL b2,LL b3,LL c1,LL c2,LL c3){ mat[0][0]=a1;mat[0][1]=a2;mat[0][2]=a3; mat[1][0]=b1;mat[1][1]=b2;mat[1][2]=b3; mat[2][0]=c1;mat[2][1]=c2;mat[2][2]=c3; } mut operator *(const mut &c){ mut res; for(int i=0; i<siz; ++i){ for(int k=0; k<siz; ++k){ for(int j=0; j<siz; ++j){ res.mat[i][j]=MODD(res.mat[i][j]+mat[i][k]*c.mat[k][j],M); } } } return res; }} AC;mut poww(LL n){ mut ans; ans.init(1,0,0,0,0,1,0,0,1); while(n){ if(n&1) ans=ans*AC; n>>=1; AC=AC*AC; } return ans;}int main(){ //int t;scanf("%d",&t); // while(t--){ while(~scanf("%lld",&N),N){ if(N==1){ puts("1"); continue; } M=200907; AC.init(1,2,1,1,0,0,0,0,1); mut ans=poww(N-2); printf("%lld\n",MODD(ans.mat[0][0]*2+ans.mat[0][1]*1+ans.mat[0][2]*1,M)); } return 0;}
- 一类常见的矩阵快速幂题型 总结
- 矩阵快速幂题型
- 面试常见题型总结
- CTF常见的题型
- 矩阵算法的基本题型
- 矩阵快速幂总结
- 矩阵快速幂总结
- 矩阵快速幂 总结
- 矩阵快速幂总结
- 数据库中几种常见的题型
- 单链表的常见题型汇总
- 常见易错点的程序题型
- 矩阵快速幂(总结)
- 针对矩阵的一类动态规划处理
- 关于二叉树的常见题型
- 有关链表的常见题型
- 关于数组操作的常见题型
- 【总结】常见编程题型总结1-数据结构&算法
- IP地址、子网掩码、网络号、主机号、网络地址、主机地址
- 搭建Spring、Spring MVC、Mybatis和Freemarker
- android ViewGroup的事件分发机制
- 前端相关-代码自动补全
- JDBC数据库操作
- 一类常见的矩阵快速幂题型 总结
- 前端相关-日期选择器控件
- java中重写equals和hashCode方法
- Java多线程目录整理
- 前端相关-表单向导
- 企业进行敏捷变革失败最主要的原因: 有这样的最资深员工
- match和index返回多个匹配项
- 2016腾讯面试
- .NET Framework 中的网络编程