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


    数论学习日记

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

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

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

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

  • 相关阅读:
    java笔记之连接数据库
    关于数据集合的使用
    ubuntu下安装MySql
    Android笔记之Broadcast广播机制
    InputStream
    Android笔记之Toast
    jqGrid 复选框实现单选
    layer弹出框包含页面
    input不显示边框
    UUID
  • 原文地址:https://www.cnblogs.com/xiangqi/p/11302947.html
Copyright © 2020-2023  润新知