大数的幂取模和素数的相关内容
基本的模运算
将a和b除以m后所得的余数相等记作$a\equiv b(mod\ m)$, 将a除以m所得的余数记作$a\ mod\ m$,并规定$0 \leq a\ mod\ m\leq m-1$。假设$a\equiv c(mod\ m)$且$b\equiv d(mod\ m)$,那么有下面的等式成立:
$$a+b \equiv c+d (mod\ m)$$
$$a-b \equiv c-d (mod\ m)$$
$$a*b \equiv c*d (mod\ m)$$
快速幂运算
反复平方法
我们把对任意的1 < x < n都有$ x^n\equiv x(mod\ n) $成立的合数n称为Carmicheal Number。对于给定的整数n,请判断它是不是Carmichael Number.
此题中,最为关键的就是如何求出$x^n\ mod\ n$的问题,因为很有可能这个幂会溢出
考虑加速幂运算的方法,同时保证不溢出。在$ n = 2^k$的条件下,有
$$ x^n = ((x^2)^2)…$$
由此,我们可以将n表示为
$$ n = 2^{k_1}+2^{k_2}+2^{k_3}….$$
利用
$x*y\ mod\ m = (x\ mod\ m) * (y\ mod\ m)\ mod\ m$
的原理
利用公式$a*b\%c=((a\%c)*b)\%c$,这样每一步都进行这种处理,这就解决了a^b可能太大存不下的问题
例如$x^{22}= x^{16} * x^4 * x^2$(22转换为2进制为10110),从而转换为
{$x^{22} \% m = (x^2 \%m) * ({x^4 \% m}) * (x^{16} \% m)\ \% m$,从而进行迭代1
2
3
4
5
6
7
8
9
10
11
12
13//时间复杂度O(logn)
typedef long long ll;
ll mod_pow(ll x, ll n, ll mod){
ll res = 1;
while(n > 0){
if (n & 1) res = res * x % mod; //标记为1,则计算此位上的余数,并与之前的余数迭代
x = x * x % mod;
n >>= 1;
}
return res;
}
第二种方法利用了二分的思想,可以达到O(logn)1
2
3
4
5
6
7
8typedef long long ll;
ll mod_pow(ll x. ll n, ll mod){
if(n == 0) return 1;
ll res = mod_pow(x * x % mod, n/2, mod); //防止x*x溢出
if (n & 1) res = res * x % mod;
return res;
}
素数的性质
素性测试
所谓素数,是指恰好有两个公约数的整数。因为n的约数都不超过n,所以只要检查2~n-1的所有整数是否能够整除n就能判定n是不是素数。如果d是n的约数。由n=d * n/d可知$min(d, n/d) \leq \sqrt n$1
2
3
4
5
6bool test_prime(int n){
for (int i = 1; i * i <= n; i++){
if (n % i == 0) return false;
}
return n != 1;
}
1 | //约数枚举,约数个数 |
1 | //这个数除约数的个数 |
素数个数
1 | //某个数以内素数的个数 |
1 | //某个区间内素数的个数 |