zoukankan      html  css  js  c++  java
  • 【模板】快速幂

    (还记得大明湖畔的快速幂吗?)

    先提一个小问题,怎么求a的n次方?

    当然是暴力。。直接乘就好啊。。

    等等,当n=10e+9怎么办?(当然我知道这玩意一般还要再模一个c)

    难不成你还想。。(不你不想)

    这时,蒟蒻默默打出一个问号。。(所以我去学了快速幂)

    ————快速幂

    原理:

    首先,有这样一个公式

    (a*b)%c=((a%c)*(b%c))%c;

    (a^b)%c=((a%c)^b)%c

    长得好奇怪。。但其实和实数运算法则一样。。

    这样就有下面的第一步优化,为了使求出来的值不超long long 

    int ans = 1;
    a = a % c;  //加上这一句
    for(int i = 1;i<=b;i++)ans = ans * a;
    ans = ans % c;

    (但是这样也还是会超。。)

    再看一下上面的公式,既然先相乘再取余先取余再相乘再取余一样,那就可以给每一步的结果ans取余。

    int ans = 1;
    a = a % c; 
    for(int i = 1;i<=b;i++)ans = (ans * a) % c;//这里再取了一次余
    ans = ans % c;

    这时的时间复杂度为O(b)

    虽然现在不会溢出,但是当b很大的时候还是会超时

    然后,有这样一个公式

    a^b%c==((a^2)b/2)%c == ((a^2 % c)b/2)%c          b为偶数

    a^b%c==(a*(a^2)b/2)%c == (a*(a^2 % c)b/2)%c         b为奇数

    这样,就可以进一步优化为:

    int ans = 1;
    a = a % c;
    k = (a*a) % c;               //相当于用k代替了a2
    if(b%2==1)
        ans = (ans * a) % c; //如果是奇数,要多求一步,可以提前算到ans中
    for(int i = 1;i<=b/2;i++) ans = (ans * k) % c;
    ans = ans % c;

    这时的时间复杂度是O(b/2)

    还是远远不够啊。。

    但是,由上面的一次优化可以发现,我们已经把a^b%c转换成了k^(b/2)%c

    而K^(b/2)%c是可以继续迭代下去的

    例如,

    下一步再令 x=(k*k)%c 偶数就是求 x^b/4 % c 奇数就是 (x^b/4 % c*a)% c
    再下一步令 y=(x*x)%c 偶数就是求 y^b/8 % c 奇数就是 (y^b/8 % c*a)% c
        ......  直到指数b ==0
    当然,对于奇数的情形会多出一项a % c,所以为了完成迭代,当b是奇数时,我们通过ans = (ans * a) % c; 来弥多出来的这一项
    int ans = 1;
    a = a % c;
    while(b>0)
    {
          if(b % 2 == 1)ans = (ans * a) % c;   //奇数,补一项
          b = b/2;
          a = (a * a) % c;
    }
    cout<<ans<<endl;

    这时的时间复杂度是O(logb)

    就是完整的快速幂算法!

    #include<iostream>
    #include<cstdio>
    using namespace std;
    long long int a,b,c;
    long long int ans=1,bent;
    int main()
    {
        scanf("%d%d%d",&a,&b,&c);
        bent=a;
        while(b)
        {
            if(b&1)
            ans=(ans*bent)%c;
            bent=(bent*bent)%c;
            b/=2;
        }
        printf("%d",ans);
        return 0;
    }

    看一道题吧。。这个是裸的快速幂(点击收获RP)先把板子打会吧。。

    (RP++!)

     

     

     
     

     

  • 相关阅读:
    二维ST表模板
    AtCoder Beginner Contest 151 *F
    [Codeforces Round #320 (Div. 2) -E. Weakness and Poorness (三分/二分)
    [Codeforces Round #320 (Div. 2) C. A Problem about Polyline (数学)
    [Codeforces Round #630 (Div. 2)]
    Codeforces Round #353 (Div. 2) E. Trains and Statistic (线段树 + dp)
    Educational Codeforces Round 13 D. Iterated Linear Function (矩阵快速幂)
    Codeforces Round #260 (Div. 1) A. Boredom (简单dp)
    Codeforces Round #245 (Div. 1) B. Working out (简单DP)
    POJ 1988 Cube Stacking (带权并查集)
  • 原文地址:https://www.cnblogs.com/Daz-Os0619/p/11469784.html
Copyright © 2011-2022 走看看