获取MAXN内的所有质数, 百万数量级内有效
bool nprime[MAXN];
vector <int> prime;
void get_prime() {
memset(nprime, 0, sizeof(nprime));
nprime[1] = 1;
for (int i=2; i*i<MAXN; i++) {
if (!nprime[i]) {
for (int j=i*i; j<MAXN; j+=i) {
nprime[j] = true;
}
}
}
for (int i=2; i<MAXN; i++) {
if (!nprime[i]) {
prime.push_back(i);
// cout << i << endl;
}
}
}
int mpf[N];//mpf[i] i的 min prime factor
void getmpf() {//获取N以内所有数的最小质因子
memset(mpf, 0, sizeof(mpf));
int sz = sqrt(N);
for (int i=2; i<=sz; i++) {
if (mpf[i]) continue;
for (int j=i*i; j<N; j+=i) {
mpf[j] = i;
}
}
for (int i=2; i<N; i++) {
if (mpf[i] == 0) mpf[i] = i;//质数的最小质因子是本身
}
// for (int i=0; i<N; i++) {
// cout << i << "=" << mpf[i] << ", ";
// }
}
//打印x所分解的质因数
for (int i=x; i>1; i = i/mpf[i]) {
cout << mpf[i] << " ";
}
phi[n]=不大于n且与n互质的正整数个数 1到n内所有phi,$O(nlogn)$
ll phi[MAXN];
void phi_table(int n) {
memset(phi, 0, sizeof(phi));
phi[1] = 1;
for (int i=2; i<=n; i++) if (!phi[i])//i是素数
for (int j=i; j<=n; j+=i) {
if (!phi[j]) phi[j] = j;
phi[j] = phi[j]/i*(i-1);//先除后乘防溢出
}
}
phi(n), $O(\sqrt n)$
int euler_phi(int n) {
int m = (int) sqrt(n+0.5);
int ans = n;
for (int i=2; i<=m; i++) {
if (n%i == 0) {
ans = ans / i * (i-1);
while (n%i == 0) n/=i;
if (n == 1) break;
}
}
if (n != 1) ans = ans / n * (n-1);
return ans;
}
a与b最大公约数
ll gcd(ll a, ll b) {
if (b == 0) return a;
return gcd(b, a%b);
}
解方程a * x + b * y = d 即 ax = d (mod b), 其中d=gcd(a,b) 整数解有d个: x, x+b/d, .., x+(d-1)b/d 若求a * x + b * y = c, 先求得a * x + b * y = gcd(a,b) 若c%gcd(a,b)=0则有解, 有d个解:x0=c/gcd(a,b)* x%b, x0+b/d, ..., x0+(d-1)b/d
void ex_gcd(ll a, ll b, ll* d, ll* x, ll* y) {
if (b == 0) {
*d = a;
*x = 1;
*y = 0;
}
else {
ex_gcd(b, a%b, d, x, y);
ll t = *x;
*x = *y;
*y = t - (a/b)*(*y);
}
}
拓展欧几里得求逆元
// a*x = 1 (mod n) -> a*x + n*y = 1
ll inv(ll a, ll n) {
ll x, y, d;
ex_gcd(a, n, x, y, d);
return d == 1 ? (x+n)%n : -1;
}
费马小定理求逆元, 要求模的是素数