NCSTOJ 1377 a^b,1378 64位整数乘法

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zhaohaibo_/article/details/82808538

求a的b次方对p取模的值,其中 1 ≤ a,b,p ≤ 1 0 9 10^9

快速幂的入门题,什么是快速幂呢? 就是快速的幂运算。

我们知道例如 a<<1 这种位运算是比直接的乘法运算 a × 2 a\times2 要快的。
快速幂之所以快 就是因为使用了这样的二进制下位运算加速计算的方法。

比如计算 a 11 a^{11} 时,
因为11的二进制为1011,即 2 3 1 + 2 2 0 + 2 1 1 + 2 0 1 = 11 {2^3}\cdot1+ {2^2}\cdot0 + {2^1}\cdot1 + {2^0}\cdot1 =11
所以我们把它拆成 a 11 = a 8 a 2 a 1 a^{11} = a^8 \cdot a^2 \cdot a^1 。每一个乘项都可以通过为运算很快地计算,整体也就很快。

至于模运算,参考公式就行。

模运算与基本四则运算有些相似,但是除法例外。其规则如下:
(a + b) % p = (a % p + b % p) % p (1)
(a – b) % p = (a % p – b % p) % p (2)
(a * b) % p = (a % p * b % p) % p (3)
(a^b) % p = ((a % p)^b) % p (4)
结合律:
((a+b) % p + c) % p = (a + (b+c) % p) % p (5)
((ab) % p * c)% p = (a * (bc) % p) % p (6)
交换律:
(a + b) % p = (b+a) % p (7)
(a * b) % p = (b * a) % p (8)
分配律:
((a +b)% p * c) % p = ((a * c) % p + (b * c) % p) % p (9)
重要定理:
若a≡b (% p),则对于任意的c,都有(a + c) ≡ (b + c) (%p);(10)
若a≡b (% p),则对于任意的c,都有(a * c) ≡ (b * c) (%p);(11)
若a≡b (% p),c≡d (% p),则 (a + c) ≡ (b + d) (%p),(a – c) ≡ (b – d) (%p),
(a * c) ≡ (b * d) (%p),(a / c) ≡ (b / d) (%p); (12)

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int a, b, p;

// calculate (a ^ b) mod p
int power(int a, int b, int p) { 
    int ans = 1 % p;
    for (; b; b >>= 1) {
        if (b & 1)
            ans = (long long)ans * a % p;
        a = (long long)a * a % p;
    }
    return ans;
}

int main() {
    cin >> a >> b >> p;
    cout << power(a, b, p) << endl;
}

上面的代码中,通过右移>> ,与& 两个运算的结合,遍历了b的二进制表示下的每一位。
在循环到第i次时(从0开始计数),变量a中存储的是 a 2 i {a^2}^i ,若b当前位为1,则把此时的变量b积累到答案ans中。


求a乘b对p取模的值,其中1≤a,b,p≤ 1 0 18 10^{18}

18次方太大,乘法运算要越界。
把快速幂次方换成乘积,相应的ans*a变成ans+a

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
long long a, b, p;

long long mul(long long a, long long b, long long p) {
	long long ans = 0;
	for (; b; b >>= 1) {
		if (b & 1) ans = (ans + a) % p;
		a = a * 2 % p;
	}
	return ans;
}

int main() {
	cin >> a >> b >> p;
	cout << mul(a, b, p) << endl;
}

猜你喜欢

转载自blog.csdn.net/zhaohaibo_/article/details/82808538