快速幂的学习
来源:互联网 发布:mac投影仪只显示桌面 编辑:程序博客网 时间:2024/06/06 02:51
莫名的看到了快速幂,发现很多地方都需要用到这个东西,于是决定学一学
在此之前先回忆一个定理 (a*b)mod n 可以转换为 (a mod n)*(b mod n)mod n
最主要的原理就是把指数拆成2进制然后再乘 这样可以大大减少乘的次数 原本计算幂函数的复杂度是O(N),现在就变成了O(Log N)
本身的快速幂也是很简单的,就是拆成二进制做乘法就可以了
代码:
int fpow(int a,int b)
{
int ans=1;
while(b>0)
{
if(b&1!=0)ans*=a;//二进制下当前的最右位判断是不是1
a*=a; //平方后供下一次乘法使用
b>>=1; //下一位
}
return ans;
}
但是这个方法有一个弊端,就是幂函数计算出来的东西本身就是巨大,有可能连unsigned long long 都存不下,所以为了计算 (a*b)mod n,就要每乘一次就mod一次
这个是白书上的代码
long long mod_pow(long long x,long long n,long long mod)
{
long long res=1;
while(n>0)
{
if(n&1)res=res*x%mod;
x=x*x%mod;
n>>=1;
}
return ans;
}
这个可能就有点难理解了,而且我在网上看到的各种证明过程都不大适合我
于是我就自己举了个例子
比如要计算2^3 mod 3 根据原版的快速幂 应该是转换为 2^(2^0)*2^(2^1)mod 3
就是 (2^1 * 2^2) mod 3
根据一开始的定理,可以转换为 (2^1 mod 3 * 2^2 mod 3)mod 3
再来看源程序,如果最末尾是1,那么res 就乘上 x % mod
在例子中实际就是运算 2^1 mod 3
然后下一句x=x*x%mod; 实际上就是在计算 2^2 mod 3
在下一个循环中判断是不是要乘上这个东西,如果末尾是1,乘上2^2 mod 3,然后再mod 3就是最后的那一步运算
期间有可能有一个疑问就是x的值被改变了之后,再平方取余不会错吗
因为这个二进制指数的幂函数,每一步算出来的就是上一步的平方,比如计算2 ^4 mod 3 ,由于x的值已经变成了2^2 mod 3,这里可能会认为
再执行这一步x=x*x%mod;就错了,实际上 2^4 mod 3 == (2^2*2^2)mod 3 == (2^2 mod 3 * 2^2 mod 3)mod 3 刚刚好
还有一个可能的疑问就是 如果上面计算的时候不是最后一步但还是mod了,其实这个是没有关系的, 因为前面乘x的时候已经mod了,所以后面
再mod 他的值也不会变。
至此,疑惑都解释清了,感觉自己对mod运算的理解更深了一步
- 快速幂的学习
- 快速幂的学习
- 快速幂的初步学习
- 矩阵快速幂的学习
- jquery的快速学习
- 快速学习的能力
- 快速学习的方法
- 学习的快速方式
- 【学习笔记】快速幂
- 矩阵快速幂(学习)
- 学习笔记:快速幂
- 快速幂学习入门
- 快速幂+快速矩阵幂学习
- 学习虚拟仪器的快速方法
- 快速学习的一些方法
- 正则表达式的快速学习
- 新知识的快速学习法
- 快速学习能力的培养
- 第六周Same Tree
- Dubbo中No provider available for the service异常
- 洛谷 P1468 派对灯 Party Lamps
- php json_encode 和 json_decode
- ngnix tomcat集群 demo1
- 快速幂的学习
- Django 设置sqlite3管理员用户密码
- php var_export 和 eval
- 继承
- 用ssh思想写的一个学生信息管理系统
- C++从文件中读写的例子及产生随机数的例子
- JavaScript中null与undefined的区别
- sql语句优化
- MySQL半同步复制--handle_slave_io--5