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

    题目描述

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

    输入输出格式

    输入格式:

     三个整数b,p,k.

    输出格式:

     输出“b^p mod k=s”

    s为运算结果

    S1:用快速幂快速的求出a^b

    原理 

    (1)如果将 a 自乘一次,就会变成 a^2 。再把 a^2 自乘一次就会变成 a^4 。然后是 a^8…… 自乘 n 次的结果是 a^(2^n) 。

    (2)a^x*a^y = a^(x+y)

    (3)将 b 转化为二进制观看一下:

    举个栗子:     a^11=a^(8+2+1)=a^8*a^2*a      11=8+2+1,转化为二进制就是1011,每个位上的一就代表1,2,4,8....的有或无

    那么怎么判断有或无呢?    用“按位与”运算 &(按位与功能是参与运算的两数各对应的二进位相与。只要对应的两个二进位都为1时,结果位就为1,比如1001&101就是0001),让a&1,判断最后一位是否是1,如果是就乘

    然后还要用到“>>”这个符号,它的作用是让整个二进制数右移一位,相当于除以二,比如1011右移就是0101,这样就可以循环的判断是否要*a^多少次方

    总的来说,如果 b 在二进制上的某一位是 1,我们就把答案乘上对应的 a^(2^n)

    来看代码实现:

    #include<iostream>
    using namespace std;
    int main()
    {
    int a,b,ans=1;
    cin>>a>>b;
    int i=a;
    while(b)//当b不等于0时,用来判断b是否已经分解完
    {
    if(b&1)//判断二进制最后一位是否为1
    {
    ans=ans*i;//如果为1就 *a^(2^n)
    }
    i=i*i;//i自乘
    b>>=1;//b右移一位,回到上面继续判断最后一位
    }
    cout<<ans;
    return 0;//华丽的return
    }

    S2 神奇的取余运算

    虽然我们已经用快速幂快速的算出了a^b,但是取余的话如果这个数太大的话评测就会炸,所以不能用常规的思路

    快速幂经常要结合取余运算。这里也讲一点。

    取余运算有一些好用的性质,包括:

    (A+B)  mod b = (A  mod b + B  mod b)  mod b  (A+B)mod b=(Amodb+Bmodbmodb

    (A×B)  mod b = ((A  mod b) × (B  mod b))  mod b  (A×B)mod b=((Amodb)×(Bmodb)modb(证明略)

    于是,我们可以在每一个while循环中都给ans取余,这样可以保证最后的答案是正确的

    S3 有机的结合

    AC代码如下:

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    using namespace std; 
    long long b,p,k,s=1;
    long long powmod(long long a,long long b1,long long c)
    {
        long long i=a;
        while(b1)
        {
            if(b1&1) 
            {
                s=(s*i)%c;
            }
            i=(i*i)%c;
            b1>>=1;
        }
        return s%c;
    }
    int main()
    {
        cin>>b>>p>>k;
        cout<<b<<"^"<<p<<" mod "<<k<<"="<<powmod(b,p,k);
        return 0;
    }

    结合S1S2的解释很容易理解

    于是这道题就结束了

  • 相关阅读:
    AT2165 Median Pyramid Hard
    AT2160 へんなコンパス / Manhattan Compass
    bzoj2863:愤怒的元首
    bzoj5336:[TJOI2018]party
    [luoguP3768]简单的数学题
    bzoj1831:[AHOI2008]逆序对
    bzoj5492:[Hnoi2019]校园旅行
    HNOI2019游记
    HDU 1102 Constructing Roads(kruskal)
    HDU 1059 Dividing
  • 原文地址:https://www.cnblogs.com/lcezych/p/10399864.html
Copyright © 2011-2022 走看看