当前位置:首页 » 操作系统 » 快速幂算法

快速幂算法

发布时间: 2022-02-05 17:34:31

㈠ 不理解矩阵快速幂如何用于求斐波那契数列第n项%m的余数,望大神讲解,越详细越好

按照正常的逻辑是只要求a[2][2]={1,1,1,0}这个矩阵的n次方就可以得到斐波那契数列的第n项(即a[0][1])的值。但是你忽略了一点,就是你在求a[0][1],a[1][0],a[1][1]的值的时候你的a[0][0]的值其实已经改变了,导致你求得的a[0][1]的值不正确,继而影响到a[1][0]和a[1][1]的值。

因此,我们在遍历这四个值的时候是不能改变其中任何一个的,只有改完之后才能去改变它的值。所以我们可以用几个变量先将求得的新矩阵各值存起来,如下:

#include<stdio.h>

inta[2][2]={1,1,1,0},b[2][2]={1,1,1,0};//使用两个二维数组表示快速幂算法要用到的矩阵

intmain()

{

intn,m,i,j,t,u;

inta1,a2,a3,a4;

while(scanf("%d%d",&n,&m)!=EOF)

{

if(m==-1&&n==-1)//当输入的m.n值为-1时结束整个算法

return0;

/*以下是对于第n项斐波那契数的计算*/

if(n==0)

a[0][0]=0;

elseif(n==1||n==2)

a[0][0]=1;

else

{

for(i=3;i<=n;i++)

{

a1=a[0][0]*b[0][0]+a[0][1]*b[1][0];

a2=a[0][0]*b[0][1]+a[0][1]*b[1][1];

  • a3=a[1][0]*b[0][0]+a[1][1]*b[1][0];

  • a4=a[1][0]*b[0][1]+a[1][1]*b[1][1];

a[0][0]=a1;

a[0][1]=a2;

a[1][0]=a3;

a[1][1]=a4;

}

}

t=a[0][0];

a[0][0]=1;//重置矩阵

a[0][1]=1;

a[1][0]=1;

a[1][1]=0;

if(m==0)

a[0][0]=0;

elseif(m==1||m==2)

a[0][0]=1;

else

{

for(j=3;j<=m;j++)

{

a1=a[0][0]*b[0][0]+a[0][1]*b[1][0];

a2=a[0][0]*b[0][1]+a[0][1]*b[1][1];

  • a3=a[1][0]*b[0][0]+a[1][1]*b[1][0];

  • a4=a[1][0]*b[0][1]+a[1][1]*b[1][1];

a[0][0]=a1;

a[0][1]=a2;

a[1][0]=a3;

a[1][1]=a4;

}

}

u=a[0][0];

a[0][0]=1;//重置矩阵

a[0][1]=1;

a[1][0]=1;

a[1][1]=0;

t=t%u;

printf("%d ",t);

}

return0;

}

还有一点,就是你的矩阵相乘后两项写错了,自己对比一下改过来吧。

这样就能得到你想要的结果了。

㈡ 求快速幂算法c语言实现程序

㈢ 次方的快速算法

次方有两种快速算法:

第一种是直接用乘法计算,例:3⁴=3×3×3×3=81。

第二种则是用次方阶级下的数相乘,例:3⁴=9×9=81

次方最基本的定义是:设a为某数,n为正整数,a的n次方表示为aⁿ,表示n个a连乘所得之结果,如2⁴=2×2×2×2=16。次方的定义还可以扩展到0次方和负数次方等等。

负数次方

由5的0次方继续除以5就可以得出5的负数次方。

例如: 5的0次方是1 (任何非零数的0次方都等于1。)

5的-1次方是0.2 1÷ 5 =0.2

5的-2次方是0.04 0.2÷5 =0.04

因为5的-1次方是0.2 ,所以5的-2次方也可以表示为0.2×0.2=0.04

5的-3次方则是0.2×0.2×0.2=0.008

由此可见,一个非零数的-n次方=这个数的倒数的n次方。

(3)快速幂算法扩展阅读:

0的次方

0的任何正数次方都是0,例:0⁵=0×0×0×0×0=0

0的0次方无意义。

一个数的0次方

任何非零数的0次方都等于1。原因如下:

通常代表3次方

5的3次方是125,即5×5×5=125

5的2次方是25,即5×5=25

5的1次方是5,即5×1=5

由此可见,n≧0时,将5的(n+1)次方变为5的n次方需除以一个5,所以可定义5的0次方为:

5 ÷ 5 = 1。

㈣ 快速幂算法原理

快速幂
顾名思义,快速幂就是快速算底数的n次幂。其时间复杂度为 O(log2N), 与朴素的O(N)相比效率有了极大的提高。

中文名
快速幂
外文名
Fast Power
时间复杂度
log(n)
性质
快速算底数的n次幂
快速
导航
实现

代码比较
原理
快速幂算法的核心思想就是每一步都把指数分成两半,而相应的底数做平方运算。这样不仅能把非常大的指数给不断变小,所需要执行的循环次数也变小,而最后表示的结果却一直不会变。
让我们先来看一个简单的例子:
3^10=3*3*3*3*3*3*3*3*3*3
3^10=(3*3)*(3*3)*(3*3)*(3*3)*(3*3)
3^10=(3*3)^5
3^10=9^5
9^5=(9^4)*(9^1)
9^5=(9^4)*(9^1)
9^5=(6561^1)*(9^1)
以下以求a的b次方来介绍[1]
把b转换成二进制数。
该二进制数第i位的权为
例如

11的二进制是1011

因此,我们将a11转化为算
实现
快速幂可以用位运算来实现
b and 1{也就是取b的二进制最低位(即第0位)判断b是否为奇数,是则为1}
b shr 1{就是去掉b的二进制最低位(即第0位)}
C++实现为
b & 1//取b二进制的最低位,判断和1是否相同,相同返回1,否则返回0,可用于判断奇偶
b>>1//把b的二进制右移一位,即去掉其二进制位的最低位
以下为pascal的实现:
var a,b,n:int64;
function f(a,b,n:int64):int64;
var t,y:int64;
begin
t:=1; y:=a;
while b<>0 do begin
if(b and 1)=1 then t:=t*y mod n;
y:=y*y mod n;{这里用了一个技巧,y*y即求出了a^(2^(i-1))不知道这是什么的看原理
a^(2^(i-1))*a^(2^(i-1))=a^(2^i)
而且一般情况下a*b mod c =(a mod c)*(b mod c) mod c}
b:=b shr 1;{去掉已经处理过的一位}
end;
exit(t);
end;
begin
read(a,b,n);{n是模}
writeln(f(a,b,n));
end.
[1]
以下为C的实现,为了方便与pascal的对照,变量全部与上面相同.可以对照查看。
递归版:[2]
ll pow(ll a,ll i){
if (i==0) return 1;
int temp=pow(a,i>>1);
temp=temp*temp%MOD;
if (i&1) temp=(ll)temp*a%MOD;
return temp%MOD;
}
非递归版:
ll f(ll a,ll b,ll n){
int t,y;
t=1; y=a;
while (b!=0){
if (b&1==1) t=t*y%n;
y=y*y%n; b=b>>1;
}
return t;
}

㈤ c语言快速幂代码

int pow( int a, int b )
{
int r = 1, base = a;
while( b != 0 )
{
if( b & 1 )
r *= base;
base *= base;
b >>= 1;
}
return r;
}

㈥ c语言,快速幂代码是什么,怎么用

所谓的快速幂,实际上是快速幂取模的缩写,简单的说,就是快速的求一个幂式的模(余)。在程序设计过程中,经常要去求一些大数对于某个数的余数,为了得到更快、计算范围更大的算法,产生了快速幂取模算法。
用递归
x^y可如下实现
unsigned long pow(int x, unsigned y)
{
unsigned long tmp;
if(!y) return 1;
tmp = pow(x, y / 2);
if(y % 2 == 0) return (tmp * tmp);
else return (tmp * tmp * x);
}

㈦ 在快速幂运算算法中,为啥把n&1换成n==1就会出错呢

对于 表达式“n&1”表示的是n与1的按位与(其业务逻辑应该是:当且仅当n为奇数时结果为1,其余时候为0,不过我也有段时间不用c++了,可能记错)
对于表达式”n==1“表示的是判断两整数是否相等(其业务逻辑是:当且仅当n为1时结果为true其余时候为false)
这两个业务逻辑不同,结果自然不同

㈧ 如何计算快速幂,比如 x^100000000次方,直接循环很慢。。谢谢了

因为 x^n = (x^(n/2))^2
根据这个公式,可以在 log2N时间内算出乘法幂

递归算法:
int pow(int x,int n)
{
if(n==1) return x;
else if(n&1) //n is odd
{
return x*pow(x,n/2);

}
else
{
return pow(x,n/2);
}

}

非递归算法:

int pow(int x,int n)
{
int temp(x),res(1);
while(n)
{
if(n&1)
{
res *= temp;
}
temp *= temp;
n>>=1;
}
return res;
}

热点内容
诺基亚密码忘了打什么电话 发布:2024-09-17 03:27:09 浏览:555
树深度优先算法 发布:2024-09-17 03:26:58 浏览:472
跳转页源码 发布:2024-09-17 03:13:05 浏览:543
html文件上传表单 发布:2024-09-17 03:08:02 浏览:784
聊天软件编程 发布:2024-09-17 03:00:07 浏览:726
linuxoracle安装路径 发布:2024-09-17 01:57:29 浏览:688
两个安卓手机照片怎么同步 发布:2024-09-17 01:51:53 浏览:207
cf编译后没有黑框跳出来 发布:2024-09-17 01:46:54 浏览:249
安卓怎么禁用应用读取列表 发布:2024-09-17 01:46:45 浏览:524
win10设密码在哪里 发布:2024-09-17 01:33:32 浏览:662