数论学习日记
嗯……好久没更新数论了,最近也有看,但还是有很多牛逼点的数论弄不懂(还是太菜了),那还是一步一个脚印慢慢来吧,那么今天就记录一下快速幂取模的算法吧。
快速幂取模就是当我们要计算类似于5^64 % 3 ,4^16 % 3 这种a^b % c类型的大数的时候需要用到的一种方法。
首先,对于一些比较小的数据比如 2^3,3^2这些当然不需要用到快速幂取模,甚至稍大点的时候我们都可以暴力解决问题,可以用long long,但是有时候数据特别庞大的时候,我们就需要做一些处理,我们已知小的很容易算出来,所以我们需要的就是把大数据变成小数据来算。那么如何去将大数据变换成小数据呢?
先用最基本的计算这种模式的代码来看一看:
#include<iostream> #include<conio.h> long long FPM( long long a, long long b,long long c) { long long sum = 1; a = a % c; for (int i = 1; i < b; i++) { sum = (sum * a)%c; } return sum; } int main(int argc, const char * argv[]) { long long a, b, c; std::cin >> a >> b >> c; std::cout << FPM(a, b, c); _getch(); return 0; }
这是计算稍大数的算法,我们可以直接降低a的大小,然后不断相乘取模,得出答案,但是如果b足够大,且a足够大,那么这种方法也是会爆栈的。
所以,我们就需要对此进行优化,假如我们要降低b的大小,比如5^64 我们可以变成 25^32 ,那么沿着这个思路,我们再去判断奇偶,如果是奇数的话,我们只需要提取出一个a就行了,假设b是奇数,我们可以变为a*(a^2)^(b/2),优化后的代码:
#include<iostream> #include<conio.h> long long FPM( long long a, long long b,long long c) { long long sum = 1; while(b) { if (b & 1) { sum = (sum * a) % c; b--; } b >>= 1; a = (a * a) % c; } return sum; } int main(int argc, const char * argv[]) { long long a, b, c; std::cin >> a >> b >> c; std::cout << FPM(a, b, c); _getch(); return 0; }
如代码所示,进入循环后先判断奇偶,如果为奇数先让sum * a,然后使b/2,不断的对a的结果取模,最后b一定会等于1,再让sum取得最终值,返回sum。
以上就是一个简单的快速幂取模的算法了。
--------------------------------------------------------------------