zoukankan      html  css  js  c++  java
  • 洛谷P1226 【模板】快速幂||取余运算

    题目描述:

    输入b,p,k的值,求bp mod k的值。其中b,p,k*k为长整型数

    题解:

    我们要让计算机很快地求出a^b

    暴力相乘的话,电脑要计算 b次。用快速幂,计算次数在 log(b) 级别,很实用。

    怎么实现呢?

    我们知:

    (1)如果将 a 自乘一次,就会变成 a2 。再把 a2 自乘一次就会变成 a4 。然后是 a8……以此类推。

    (2)axay = a(x+y)



    过程会是这样:

    ·假设我们拿到了 aa,并且 b = 11。想求 a11,但是又不想乘11次,有点慢。

    ·稍稍观察一下 b = 11,二进制下是 b = 1011

    ·制作一个 base。现在 base = a,表示的是,a1 = a

    ·制作一个 ans,初值 1,准备用来做答案。


    while(b > 0)
    {
    if(b & 1)
        ans *= base;
    
    /*关于 b & 1:
    x & y 是二进制 x 和 y 的每一位分别进行“与运算”的结果。
    与运算,即两者都为 1 时才会返回 1,否则返回 0。
    那么 b & 1
    
              二进制
    b     =    1011
    1     =    0001
    b&1   =    0001
    
    因为 1(二进制)的前面几位全部都是 0,
    所以只有 b 二进制最后一位是 1 时,b & 1 才会返回 1。)*/

    ·然后 base通过自乘一次,使自己变成 a2

    base *= base;

    同时

    b >>= 1;
    }

    接着再按照以上顺序循环,以此类推。



    但有时候快速幂乘的过程中会爆掉,所以我们用到快速加

    原理相同,只是变一下符号。

    附上代码:

    #include<stdio.h>
    long long b,p,k;
    long long ksj(long long x,long long y)
    {
        long long cnt=0;
        while(y)
        {
            if(y%2)
                cnt=(cnt+x)%k;
            x=(x+x)%k;
            y/=2;
        }
        return cnt;
    }
    long long ksm(long long x,long long y)
    {
        long long cnt=1;
        while(y)
        {
            if(y%2)
                cnt=ksj(cnt,x)%k;
            x=ksj(x,x)%k;
            y/=2;
        }
        return cnt;
    }
    int main()
    {
        scanf("%lld%lld%lld",&b,&p,&k);
        long long ans=ksm(b,p);
        if(p!=0)
            printf("%lld^%lld mod %lld=%lld",b,p,k,ans);
        else
            printf("%lld^%lld mod %lld=0",b,p,k);        
    }
  • 相关阅读:
    Mark
    个人作业——软件工程实践总结作业
    个人作业——软件产品案例分析
    个人技术博客(α)
    软件工程实践_结对Task2_ student_department_matching
    软件工程实践_Task2_sudoku
    软件工程实践_Task1
    面向对象程序设计_Task7_Summary
    面向对象程序设计__Task6_Calculator1.6.2
    C++课堂作业_02_PAT1025.反转链表
  • 原文地址:https://www.cnblogs.com/jiangminghong/p/9819648.html
Copyright © 2011-2022 走看看