Loading

数论学习日记五—快速幂取模

数论学习日记

 

嗯……好久没更新数论了,最近也有看,但还是有很多牛逼点的数论弄不懂(还是太菜了),那还是一步一个脚印慢慢来吧,那么今天就记录一下快速幂取模的算法吧。

 

快速幂取模就是当我们要计算类似于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。

 

以上就是一个简单的快速幂取模的算法了。

--------------------------------------------------------------------

posted @ 2019-08-05 14:49  eveilcoo  阅读(193)  评论(0编辑  收藏  举报