模幂函数 (将网上搜到的大作,做个整理解释给咱菜鸟看,,,,呵呵)
来源:互联网 发布:田众和时代网络 编辑:程序博客网 时间:2024/05/22 09:51
由于矩阵乘法具有结合律,因此A^4 = A * A * A * A = (A*A) * (A*A) = A^2 * A^2。我们可以得到这样的结论:当n为偶数时,A^n = A^(n/2) * A^(n/2);当n为奇数时,A^n = A^(n/2) * A^(n/2) * A (其中n/2取整)。这就告诉我们,计算A^n也可以使用二分快速求幂的方法。例如,为了算出A^25的值,我们只需要递归地计算出A^12、A^6、A^3的值即可。根据这里的一些结果,我们可以在计算过程中不断取模,避免高精度运算。
在Miller Rabbin测试素数这篇文章里的Modular_Exp函数里,就用到了快速幂取模的思想。
这里总结下。
求a^b%c(这就是著名的RSA公钥的加密方法)
当a,b很大时,直接求解这个问题不太可能
你能想到哪些优化呢?
算法1:直观上,也许最容易想到的是利用a*b%c=((a%c)*b)%c,这样每一步都进行这种处理,这就解决了a^b可能太大存不下的问题,但这个算法的时间复杂度依然是O(n),根本没有得到优化。当b很大时运行时间会很长
算法2:另一种算法利用了二分的思想,可以达到O(logn)。
可以把b按二进制展开为b=p(n)*2^n+p(n-1)*2^(n-1)+…+p(1)*2+p(0) (可用>>=移位来判断每一位,计算下边的每一项)
其中p(i) (0<=i<=n)为0或1
这样a^b=a^(p(n)*2^n+p(n-1)*2^(n-1)+...+p(1)*2+p(0))
=a^(p(n)*2^n)*a^(p(n-1)*2^(n-1))*...*a^(p(1)*2)*a^p(0),,,,,,,,,,,,,,,,,,,,(1)
对于p(i)=0的情况,a^p(i)*2^(i-1)=a^0=1,不用处理
我们要考虑的仅仅是p(i)=1的情况
a^(2^i)=(a^(p(i)*2(i-1)))^2
利用这一点,我们可以递推地算出所有的a^(2^i)
当然由算法1的结论,我们加上取模运算a^(2^i)%c=((a^(2(i-1))%c)*a^(2(i-1)))%c((1)中的每一项,即a^b%n)
而上边还不够简练,a^2^i=a*a*a,,,,,所以a^2^3%c=((a*a)%c*(a*a)%c)*%c*((a*a)%c*(a*a)%c)%c,,,,,yi以此类推,刚好是一个循环t=(t*t)%c;
于是再把所有满足p(i)=1的a^(2^i)%c按照算法1乘起来再%c就是结果(公式 :(x*y)%z=((x%z)*(y%z))%z )
即二进制扫描从最高位一直扫描到最低位。
在随机素数测试算法中要用到模幂运算,在O(lgn)的时间内产生模幂结果是非常有用的。
在诸如RSA等算法中都要用到求a^n mod p的运算,例如费马小定理(a^(n-1) mod n = 1,p是a的非素数因子)
及rsa算法用到的费马定理的推广(a^(y(n))mod n = 1,y(n)为n的欧拉函数)等等都需要用到模幂运算,那么
怎么能快速的到模幂运算结果其实原理很简单,这是我用english写的,希望没写错,呵呵
Basing on the two simple theories:
1,(x*y)%z=((x%z)*(y%z))%z
2,(x^y)%z=((x%z)^y)%z
To solve the y=(g^x)%p problem left shifting x until x become 0,compute g^x by computing
k=(g^(x/2)%p) and g^x=k*k or g^x=k*k*g 。so this algorithm is O(lgn) which is also linear。
This is a simple and recursive algorithm.
这是我写的参考程序 (仅供参考)
class MMath{
public:
static int power(int g,int p,int n){
int s,u;
if(n==0)return 1;
else {
s = power(g,p,n>>1);
u = s*s;
if(n%2==0)
return u%p;
else
return u*g%p;
}
}
static bool prime_judge(int n){
if(power(2,n,n-1)!=1)return false;
else return true;
}
}
另外附一个根据费马定理写的素数测试程序(会产生错误,伪素数如1387等)
MillerRabin测试还没有想好怎么写程序呢。
- 模幂函数 (将网上搜到的大作,做个整理解释给咱菜鸟看,,,,呵呵)
- 最近看的电视剧,蛮好看的,做个记录,呵呵
- 网上搜索到的一些资料,做个备份
- 没事弄个标记,嗯~转且算是给淘宝做的吧,呵呵
- 网上搜的信息,给自己做纪念
- 我的第一个发布到网上的程序,已经超过二十家网站收录了,呵呵,高兴
- 网上搜到的关于ANSI文本的解释
- AngularJs笔记(看菜鸟教程整理的)
- 多么给力的锁啊,呵呵!! 不解释
- 从网上下了个人品测试,大家来看看你人品 呵呵
- 给初学者看的,笔记本术语解释
- 要做的事情(给自己做个备忘)
- (转)网上看的一篇文章,感觉会给程序员一些启发
- 呵呵,新年到乐,今年的计划要整理一下乐,呵呵
- Javascript prototype 笔记 网上看的,整理了一下排版
- 给Source Insight做个外挂系列之二--将本地代码注入到Source Insight进程
- 给Source Insight做个外挂系列之二--将本地代码注入到Source Insight进程
- 刚做了一个用JDBC把ORACLE数据转移到SYBASE的小程序,想和大家分享。有意者可以发邮件给我!呵呵!
- UBUNTU12.04服务器版配置dns服务器步骤
- jetbrick-template 1.1.1 发布,增强layout功能
- rsa加密字符串 的思想,,,,菜菜鸟们努力
- iOS手势识别的详细使用(拖动,缩放,旋转,点击,手势依赖,自定义手势)
- 调用webservice
- 模幂函数 (将网上搜到的大作,做个整理解释给咱菜鸟看,,,,呵呵)
- 适配iOS7之—UITableView和UISearchBar
- 开启oracle的flashback闪回功能
- Java开源知识库:XWiki安装(Windows平台)
- 2013秋13级预备队集训练习1 K - The Collatz Sequence
- C语言实现状态机
- Effective Objective-C 2.0: Item 30: Use ARC to Make Reference Counting Easier
- 开启手机LogCat:Unable to open log device ‘/dev/log/main’: No such file or directory
- Rabin_Miller