快速幂 :
ll calc(ll x,ll y){
ll ans = 1;
while(y){
if(y & 1) ans = (ans * x) % k;
x = (x * x) % k;
y >>= 1;
}
return ans % k;
}
时间复杂度是logn;
运用二进制拆分;
快速乘:
应用于大整数相乘时,由于相乘后的结果会爆掉long long,所以化乘法为加法,然后取模。
a * b的实质是b个a相加,可以参考快速幂的思想运算。
a * b = 2 * (a * b / 2); b为偶数
a * b = 2 * (a * (b - 1) / 2 + a) ,b为奇数.
将b二进制拆分,然后进行加法即可。
ll ksc(ll a,ll b){
ll ans = 0;
while(b){
if(b & 1){
ans = (ans + a) % mod;
b --;
}
b >>= 1;
a = (a * 2) % mod;
}
return ans;
}
埃氏筛:
非常朴素的筛法,复杂度是O(nlogn)的。
欧拉筛:
void euler(){
not_p[0] = not_p[1] = 1;
for(int i = 2;i <= n;i ++){
if(!not_p[i]) p[++ tot] = i;
for(int j = 1;j <= tot && p[j] * i <= n;j ++){
not_p[i * p[j]] = 1;
if(i % p[j] == 0) break;
}
}
return;
}
关键在于跳出循环的条件的理解,i % p[j] == 0,这句话决定了所有的数都只能被他最小的质因数筛去。
p[i] 为 n的最小质因数;
考虑 n = m * p[i] ,n = m1 * p[i + k],则p[i] < p[i + k];
n 只会被p[i] 筛去,因为p[i] != p[i + k];