快速幂算法模板||取余运算

快速幂算法模板

m k m^k mk%p,时间复杂度 O(log k k k)。

int qmi(int m, int k, int p)
{
    int res = 1, t = m;
    while (k)
    {
        if (k&1) res = res * t % p;
        t = t * t % p;
        k >>= 1;
    }
    return res;
}

关于 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。挺巧妙的,并且很快。)

int quickPower(int a, int b)//是求a的b次方
{
    int ans = 1, base = a;//ans为答案,base为a^(2^n)
    while(b > 0)//b是一个变化的二进制数,如果还没有用完
    {
        if(b & 1)//&是位运算,b&1表示b在二进制下最后一位是不是1,如果是:
            ans *= base;//把ans乘上对应的a^(2^n)

        base *= base;//base自乘,由a^(2^n)变成a^(2^(n+1))
        b >>= 1;//位运算,b右移一位,如101变成10(把最右边的1移掉了),10010变成1001。现在b在二进制下最后一位是刚刚的倒数第二位。结合上面b & 1食用更佳
    }
    return ans;
}

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

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

(A+B) mod b = (A mod b + B mod b) mod b
(A×B) mod b = ((A mod b) × (B mod b)) mod b
证明都很简单,如果要说服自己的话拿起笔试试吧

于是快速幂过程中可以
实际在编程或者比赛的时候 尽量把 *= 与 % m 分开写 不要问我问什么 我也不知道为什么要这么写 在洛谷的编译器上 尽量分开写 不然有些测试样例通不过

			方法1:
            ans *= base;
            ans %= m;
            
			 base *= base;
       		 base %= m;
            方法:2:
            ans = ans * base % m;
            base = base * base % m;

【注意事项】
1、每进行一步运算时都要把得到的答案对p取模,否则会只有 28分。

2、b m p ans 都要定义成 long long 型变量,不然会只有 42分。

3、不要认为运算过程中对答案取模就够了,再输出答案的时候不要忘记把最终的答案再对p取一次模,否则就会只有 84分。

4、结合以上几点注意事项的快速幂程序就可以得到 100分了。

  while(b > 0)
    {
        if(b & 1)
        {
            ans *= base;
            ans = ans * base
            ans %= m;
        }

        base *= base;
        base %= m;
        b >>= 1;
    }

能保证这样下来最后的结果与“先乘到最后,再取余”的结果一样。
案例

你可能感兴趣的:(Java/C++/C,Jottings,简短笔记)