蓝桥杯:递推求值(快速幂,矩阵快速幂)
2017-05-23 17:08
183 查看
快速幂就是快速计算m^n
“快”主要体现在它把复杂度从一般循环计算的o(n)级别降低到了o(logn)级别。
一般情况下,m^n=m*m*m*…*m,实现就是用一般的循环计算来实现。
而快速幂的想法是将m^n表示成m^(2^a1+2^a2…),2^a1+2^a2+…=n;
我们现在假设n=10;
一般想法就是将m乘以10次,用简单的for循环就能实现。
这个是快速幂的代码
快速幂想法就是m^10=m^(2^3+2^1)=m^(2^3)*m^(2^1)=m^8*m^2
在代码中,m=m*m让m以指数倍的速度增长着。
m一开始不变,在循环时,m的值依次为 m^2 m^4 m^8 m^16 …那0
n=10时,我们只需要筛选出我们需要的,即m^2 , m^8
而 if(n%2==1) 就是筛选条件。n%2==1等价于n的二进制末位是1
10的二进制表示是1010,很明显为1项才是我们需要的
n>>1的作用是去掉二进制最后一位,即1010变成了101
当n的末位为1时,m就会正好变到了我们想要的值,这个可以自己手动执行看看。
矩阵快速幂其实就是把m换成矩阵,然后自己写一下矩阵乘法就行。
最近在刷蓝桥杯上的题目,那个递推求值就可以用矩阵快速幂做。
题目如下:
已知递推公式:
F(n, 1)=F(n-1, 2) + 2F(n-3, 1) + 5,
F(n, 2)=F(n-1, 1) + 3F(n-3, 1) + 2F(n-3, 2) + 3.
初始值为:F(1, 1)=2, F(1, 2)=3, F(2, 1)=1, F(2, 2)=4, F(3, 1)=6, F(3, 2)=5。
输入n,输出F(n, 1)和F(n, 2),由于答案可能很大,你只需要输出答案除以99999999的余数。
题目n的取值范围很大,所以一般的方法肯定会超时,用快速幂降低时间复杂度就很必要。
代码如下:
这道题目主要是需要根据题意,得到关于矩阵的递推方程
根据这个方程做题就可以了。
“快”主要体现在它把复杂度从一般循环计算的o(n)级别降低到了o(logn)级别。
一般情况下,m^n=m*m*m*…*m,实现就是用一般的循环计算来实现。
而快速幂的想法是将m^n表示成m^(2^a1+2^a2…),2^a1+2^a2+…=n;
我们现在假设n=10;
一般想法就是将m乘以10次,用简单的for循环就能实现。
这个是快速幂的代码
int qmul(int m,int n) { int res=1;//存储结果 while(n) { if(n%2==1) res*=m; m=m*m; n>>=1;//二进制去掉最后一位 } return res; }
快速幂想法就是m^10=m^(2^3+2^1)=m^(2^3)*m^(2^1)=m^8*m^2
在代码中,m=m*m让m以指数倍的速度增长着。
m一开始不变,在循环时,m的值依次为 m^2 m^4 m^8 m^16 …那0
n=10时,我们只需要筛选出我们需要的,即m^2 , m^8
而 if(n%2==1) 就是筛选条件。n%2==1等价于n的二进制末位是1
10的二进制表示是1010,很明显为1项才是我们需要的
n>>1的作用是去掉二进制最后一位,即1010变成了101
当n的末位为1时,m就会正好变到了我们想要的值,这个可以自己手动执行看看。
矩阵快速幂其实就是把m换成矩阵,然后自己写一下矩阵乘法就行。
最近在刷蓝桥杯上的题目,那个递推求值就可以用矩阵快速幂做。
题目如下:
已知递推公式:
F(n, 1)=F(n-1, 2) + 2F(n-3, 1) + 5,
F(n, 2)=F(n-1, 1) + 3F(n-3, 1) + 2F(n-3, 2) + 3.
初始值为:F(1, 1)=2, F(1, 2)=3, F(2, 1)=1, F(2, 2)=4, F(3, 1)=6, F(3, 2)=5。
输入n,输出F(n, 1)和F(n, 2),由于答案可能很大,你只需要输出答案除以99999999的余数。
题目n的取值范围很大,所以一般的方法肯定会超时,用快速幂降低时间复杂度就很必要。
代码如下:
#include<stdio.h> #include<string.h> #define N 7 #define mod 99999999 typedef struct Matrix{ long long int mat ; }Matrix; Matrix unit={ 1,0,0,0,0,0,0, 0,1,0,0,0,0,0, 0,0,1,0,0,0,0, 0,0,0,1,0,0,0, 0,0,0,0,1,0,0, 0,0,0,0,0,1,0, 0,0,0,0,0,0,1 }; Matrix base={ 0,1,0,0,2,0,5, 1,0,0,0,3,2,3, 1,0,0,0,0,0,0, 0,1,0,0,0,0,0, 0,0,1,0,0,0,0, 0,0,0,1,0,0,0, 0,0,0,0,0,0,1 }; Matrix ans={ 6,0,0,0,0,0,0, 5,0,0,0,0,0,0, 1,0,0,0,0,0,0, 4,0,0,0,0,0,0, 2,0,0,0,0,0,0, 3,0,0,0,0,0,0, 1,0,0,0,0,0,0, }; Matrix mul(Matrix a,Matrix b) { Matrix res; memset(res.mat,0,sizeof(res.mat)); int i,j,k; for(i=0;i<N;i++) { for(j=0;j<N;j++) { for(k=0;k<N;k++) { res.mat[i][j]+=a.mat[i][k]*b.mat[k][j]; res.mat[i][j]%=99999999; } } } return res; } Matrix qmul(Matrix m,long long int n) { Matrix res; res=unit; while(n!=0) { if(n%2==1)res=mul(m,res); m=mul(m,m); n=n>>1; } return res; } int main() { long long int n; scanf("%lld",&n); if(n==1) { printf("2\n3\n"); } else if(n==2) { printf("1\n4\n"); } else if(n==3) { printf("6\n5\n"); } else { base=qmul(base,n-3); ans=mul(base,ans); printf("%lld\n%lld\n",ans.mat[0][0],ans.mat[1][0]); } return 0; }
这道题目主要是需要根据题意,得到关于矩阵的递推方程
F(n,1) 0 ...0 0 1 0 0 2 0 5 F(n-1,1) 0 ...0 F(n,2) 0 ...0 1 0 0 0 3 2 3 F(n-1,2) 0 ...0 F(n-1,1) 0 ...0 1 0 0 0 0 0 0 F(n-2,1) 0 ...0 F(n-1,2) 0 ...0 = 0 1 0 0 0 0 0 x F(n-2,2) 0 ...0 F(n-2,1) 0 ...0 0 0 1 0 0 0 0 F(n-3,1) 0 ...0 F(n-2,2) 0 ...0 0 0 0 1 0 0 0 F(n-3,2) 0 ...0 1 0 ...0 0 0 0 0 0 0 1 1 0 ...0
根据这个方程做题就可以了。
相关文章推荐
- 蓝桥杯算法提高——递推求值(矩阵快速幂)
- 蓝桥杯 递推求值(矩阵快速幂)
- 蓝桥杯 算法提高 递推求值 【矩阵快速幂】
- nyoj 301 递推求值(矩阵快速幂)
- 蓝桥杯历届试题----斐波那契(矩阵快速幂)
- 15年第六届蓝桥杯第九题_(矩阵快速幂优化的动态规划)
- nyoj 301 递推求值(矩阵快速幂)
- 蓝桥杯 垒骰子(矩阵快速幂)
- nyoj 301 递推求值(矩阵快速幂)
- nyist 301 递推求值(矩阵快速幂)
- nyoj 301 递推求值(矩阵快速幂)
- NYOJ 301 递推求值(矩阵快速幂)
- nyoj 301 递推求值(矩阵快速幂)
- nyoj 301 递推求值(矩阵快速幂)
- nyoj 301 递推求值(矩阵快速幂)
- nyoj 301 递推求值(矩阵快速幂)
- 【矩阵快速幂*模板】nyoj 301 递推求值
- NYOJ——301递推求值(矩阵快速幂)
- nyoj 301 递推求值(矩阵快速幂)
- nyoj 301 递推求值(矩阵快速幂)