zoukankan      html  css  js  c++  java
  • 快速幂及求逆元

    求a^k % p,(1 <= a, k, p <=10^9)

    #include <iostream>
    #include <algorithm>
    using namespace std;
    typedef long long LL;
    LL qmi(int a, int b, int p)
    {
        LL res = 1;
        while(b)
        {
            if(b & 1) res = res * a % p;
            b >>= 1;
            a = (LL)a * a % p;
        }
        return res;
    }
    int main()
    {
        int n;
        cin>>n;
        while(n--)
        {
            int a,b,p;
            cin>>a>>b>>p;
            cout<<qmi(a,b,p)<<endl;
        }
    }

    如果用暴力的话,那么就是O(n) = 10^9, 而快速幂则是logn级别的,log10^9 = 30;

    原理是:比如4^5 = 4^2^0+4^2^2,

    第一步先产生4^2^0 = 4 mod 10;

    第二步再产生4^2^1 = 6 mod 10;

    第三步再是生4^2^2 = 6 mod 10;

    可以看到每一步都是前面的平方,那么快速也是一样,一开始底数a = a , a = a * a = a^2, a = a^2 * a ^2 = a^4, a = a^4 * a^4 = a^8;

    有1的话,即(a&1)res = res * a; a >>= 1; a = a * a % p;

    注意:我总是会忘记if(a & 1)这个条件。4^101, res = 4, res = 4 * 4^4 = 4^5;所以指数看起来是和,但是当加到底数里面来得时候就是不断的平方然后和之前的乘积了。

    res = 1;if(a & 1) res = res * a % p; a >>= 1; a = a * a;

    同余逆元:

    a/b 同余 a * x mod m 

    b * x 同余 1 mod m

    费马定理:b、p互质,那么b^p-1 同余 p。(如2 ^ (3-1) = 4 % 3 = 1, 2^(5-1) = 16 % 5 = 1, 5^(3-1) = 25 % 3 = 1, 3^(5-1) = 81 % 5  = 1)

    b * b^p-2 同余 p

    那么b % p的乘法逆元就是b ^ p - 2。(如果b和p的余数不为0,那么就一定不存在逆元) (如果b、p互质,那么由费马定理一定存在逆元b^(p-2),因为质数都是>=2.

    这样就可以用快速幂来求出:

    #include <iostream>
    #include <algorithm>
    #include <cstdio>
    typedef long long LL;
    using namespace std;
    int qmi(int a, int p, int k)
    {
        int res = 1;
        while(p)
        {
            if(p & 1)res = (LL)res * a % k;
            p >>= 1;
            a = (LL)a * a % k;
        }
        return res;
    }
    int main()
    {
        int n;
        scanf("%d",&n);
        while(n--)
        {
            int a,p;
            scanf("%d%d",&a,&p);
            int res = qmi(a, p - 2, p);
            if(a % p) printf("%d
    ",res);
            else printf("impossible
    ");
        }
    }
    int res = qmi(a, p - 2, p);
    if(a % p) printf("%d
    ",res);
    注意这里不能用res返回的结果是0还是1来判断,因为如果a = 2, p = 2, 就等于1了,所以要看a和p是不是没有合数。
  • 相关阅读:
    Swift
    Swift
    Swift
    Swift
    iOS 判断某一日期是否在一日期区间
    iOS 本地推送通知
    iOS json解析中包含“ ”等解析出错
    iOS UILabel两侧加阴影
    IOS 设置ios中DatePicker的日期为中文格式
    [分享] 关于App Store下载到一半发生错误的问题 [复制链接]
  • 原文地址:https://www.cnblogs.com/longxue1991/p/12725394.html
Copyright © 2011-2022 走看看