您的位置:首页 > 其它

蓝桥杯:递推求值(快速幂,矩阵快速幂)

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循环就能实现。

这个是快速幂的代码

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


根据这个方程做题就可以了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: