快速幂
#define ll long long
const int mod=1000000007;
//快速幂朴素版本 b是底数,p是幂
int pow(ll b,ll p){
int r=1;
while(p>0){
if(p&1) r*=b;
b*=b;
p>>=1;
}
return r;
}
//快速幂取模版本
int pow(ll b,ll p){
int r=1;
while(p>0){
if(p&1) r=r*b%mod;
b=b*b%mod;
p>>=1;
}
return r%mod;
}
GCD
#define ll long long
ll gcd(ll x,ll y) {//求x,y最大公约数
while(y^=x^=y^=x%=y);
return x;
}
exGCD
扩展欧几里得用来求
ax+by=gcd(a,b)(a,b为常数)的方程的一组整数解。
注意:求出来的(x0,y0)的解可能是正整数或者负整数。对于题目要根据通解形式来得到所求答案。
所有解为(x0+kb/gcd(a,b),y0-k*a/gcd(a,b))(k∈Z)
#define ll long long
ll exgcd(ll a,ll b,ll &x,ll &y) {//扩展欧几里得
if(b==0) return x=1,y=0,a;
int r=exgcd(b,a%b,x,y);
std::tie(x,y) =std::make_tuple(y,x-(a/b)*y);
return r;
}
素数筛
const int maxn = 10000000;
bool not_prime[maxn+5];
int prime[maxn+5], tot = 0,n;//素数放在prime数组里面
void init() {
for (int i = 2; i <= n; i++) {
if (!not_prime[i]) prime[++tot] = i;
for (int j = 1; j <= tot && i * prime[j] <= n; j++) {
not_prime[i * prime[j]] = true;
if (i % prime[j] == 0) break;
}
}
}
欧拉函数
对正整数n,欧拉函数φ(n)是小于或等于n的正整数中与n互质的数的数目。
例如φ(8) = 4,因为1,3,5,7均和8互质。
ll get_phi(ll n) {//欧拉函数
ll phi = 1;
for (int i = 2; i <= n/i; i++) {
if (n % i == 0) {
phi *= (i - 1);
n /= i;
while (n % i == 0) phi *= i, n /= i;
}
}
if (n > 1) phi *= (n - 1);
return phi;
}
线性欧拉筛上的欧拉函数
const int maxn = 10000000;
bool not_prime[maxn+5];
int prime[maxn+5], tot = 0, phi[maxn+5],n;
void init_phi() {//欧拉筛上的欧拉函数
for (int i = 2; i <= n; i++) {
if (!not_prime[i]) prime[++tot] = i, phi[i] = i - 1;
for (int j = 1; j <= tot && i * prime[j] <= n; j++) {
not_prime[i * prime[j]] = true;
if (i % prime[j] == 0) {
phi[i * prime[j]] = phi[i] * prime[j];
break;
}
phi[i * prime[j]] = phi[i] * (prime[j] - 1);
}
}
}