算法录 之 快速幂快速乘和矩阵快速幂。
2015-12-22 15:11
453 查看
1:
问题如下:
求 a^n % m 的值是多少?n是1到10^18次方的一个整数。
求一个数的n次方,朴素的算法就是直接for循环,O(N)的复杂度。
但是对于这个问题n实在是太大了,O(N)也会超时,那么需要更快的算法,快速幂算法。
要求 a^n,如果知道了 a^(n/2) 次方的话,再来个平方就可以了。
那么按照这个思路就能运用分治的思想了。
代码如下:
如上运用分治的思想,只需要logN的复杂度就可以得到答案。
2:
问题如下:
f(1)=1, f(2)=1 , f(n)=a*f(n-1)+b*f(n-2),输出n和m,求 f(n) % m 的值。n是1到10^18次方的数。
朴素的想法同上,直接一个for循环递推过去,这样复杂度是O(N)的,还是比较慢。
然后想到高中的数学问题,用特征方程求这个递推式的非递推通项方程,求出是 f(n)=c1*x1^n+c2*x2^n ,这样的话应用前面的快速幂就可以求解了。
但是x1和x2大部分情况是小数,这是求出来会有误差而且没法取模,并不能算出精确值来。
考虑矩阵这种数学工具,构造矩阵:
则求 f(n) 的话如下:
那么只要用快速幂求出矩阵的n-2次方来,因为都是整数,所以不会有精度问题,也就得到了正确答案。
也就是矩阵快速幂。
3,快速乘:
问题:
求 (a*b) % m 的值,其中 a,b,m 是1到10^18。
如果直接乘的话,因为a和b还有m都很大,那么会溢出long long,所以需要一些方法。
朴素的想法是用数组模拟高精度,但是比较麻烦。
还有更好的方法:
求乘法的列竖式,
1234*213=1234*3+1234*10*1+1234*10^2*2;
那么如果变成二进制的话 10101 × 1011 = 10101*1+10101*2^1*1+10101*2^2*0+10101*2^3*1;
这样代码如下:
就是模拟了二进制的竖式乘法,因为每次最多×2,所以不会溢出。
这样的复杂度是 logN 的。
问题如下:
求 a^n % m 的值是多少?n是1到10^18次方的一个整数。
求一个数的n次方,朴素的算法就是直接for循环,O(N)的复杂度。
但是对于这个问题n实在是太大了,O(N)也会超时,那么需要更快的算法,快速幂算法。
要求 a^n,如果知道了 a^(n/2) 次方的话,再来个平方就可以了。
那么按照这个思路就能运用分治的思想了。
代码如下:
int _pow(int a,long long n,int m) { if(n==0) return 1 % m; long long t=_pow(a,n/2,m); if(n%2==1) return (t*t*a) % m; else return (t*t) % m; }
如上运用分治的思想,只需要logN的复杂度就可以得到答案。
2:
问题如下:
f(1)=1, f(2)=1 , f(n)=a*f(n-1)+b*f(n-2),输出n和m,求 f(n) % m 的值。n是1到10^18次方的数。
朴素的想法同上,直接一个for循环递推过去,这样复杂度是O(N)的,还是比较慢。
然后想到高中的数学问题,用特征方程求这个递推式的非递推通项方程,求出是 f(n)=c1*x1^n+c2*x2^n ,这样的话应用前面的快速幂就可以求解了。
但是x1和x2大部分情况是小数,这是求出来会有误差而且没法取模,并不能算出精确值来。
考虑矩阵这种数学工具,构造矩阵:
则求 f(n) 的话如下:
那么只要用快速幂求出矩阵的n-2次方来,因为都是整数,所以不会有精度问题,也就得到了正确答案。
也就是矩阵快速幂。
3,快速乘:
问题:
求 (a*b) % m 的值,其中 a,b,m 是1到10^18。
如果直接乘的话,因为a和b还有m都很大,那么会溢出long long,所以需要一些方法。
朴素的想法是用数组模拟高精度,但是比较麻烦。
还有更好的方法:
求乘法的列竖式,
1234*213=1234*3+1234*10*1+1234*10^2*2;
那么如果变成二进制的话 10101 × 1011 = 10101*1+10101*2^1*1+10101*2^2*0+10101*2^3*1;
这样代码如下:
long long multi(long long a,long long b,long long m) { long long ans=0; while(b) { if(b&1) (ans+=a) %= m; (a=a*2) %= m; b/=2; } return ans; }
就是模拟了二进制的竖式乘法,因为每次最多×2,所以不会溢出。
这样的复杂度是 logN 的。
相关文章推荐
- android 一个应用两个入口一个应用两个快捷方式(不同图标显示)
- 记录Controller处理时间
- Spring 任务调度配置及使用
- Android开发笔记(二十三)文件对话框FileDialog
- 这30类CSS选择器 你必须记在脑袋里!
- JVM 参数配置及详解 -Xms -Xmx -Xmn -Xss 调优总结
- bootlader时钟初始化
- 操作系统之分页分段介绍
- 布局动画之LayoutTransition使用
- Java并发编程之三:volatile关键字解析 转载
- HTML中的div标签
- iOS UITabBarController的使用
- MTK6572 串口模拟sim卡开发笔记
- 判断当前网络状态 显示网络小图标
- Filter进行登录验证时循环重定向的解决方法(转)
- C++学习笔记-泛型算法
- C++学习笔记-泛型算法
- 程序报0xc0150002和0xc000007b错误的解决方法
- 闪客工具:微信本地调试工具
- Android样式开发之selector