将雪菜大佬的模板转写为java形式,C++见大佬原文AcWing @yxc
试除法判定质数
boolean is_prime(int x) {
if (x < 2)
return false;
for (int i = 2; i <= x / i; i++)
if (x % i == 0)
return false;
return true;
}
试除法分解质因数
void divide(int x) {
for (int i = 2; i <= x / i; i++) {
if (x % i == 0) {
System.out.print(i + "*");
x /= i;
i--;
}
}
System.out.println(x);
}
朴素筛法求素数
static int[] primes; // primes[]存储所有素数
static boolean[] st; // st[x]存储x是否被筛掉
void get_primes(int n) {
int cnt=0;
for (int i = 2; i <= n; i++) {
if (st[i])
continue;
primes[cnt++] = i;
for (int j = i + i; j <= n; j += i)
st[j] = true;
}
}
线性筛法求素数
static int[] primes; // primes[]存储所有素数
static boolean[] st; // st[x]存储x是否被筛掉
void get_primes(int n) {
int cnt = 0;
for (int i = 2; i <= n; i++) {
if (!st[i])
primes[cnt++] = i;
for (int j = 0; primes[j] <= n / i; j++) {
st[primes[j] * i] = true;
if (i % primes[j] == 0)
break;
}
}
}
试除法求所有约数
ArrayList<Integer> get_divisors(int x)
{
ArrayList<Integer> res=new ArrayList<Integer>();
for (int i = 1; i <= x / i; i ++ )
if (x % i == 0)
{
res.add(i);
if (i != x / i) res.add(x / i);
}
return res;
}
约数个数&约数之和
对于一个大于1正整数N可以分解质因数: N = p1^c1 * p2^c2 * … *pk^ck
如 100=2 * 2 * 5 * 5 = 22 * 52
约数个数: (c1 + 1) * (c2 + 1) * … * (ck + 1)
约数之和: (p1^0 + p1^1 + … + p1^c1) * … * (pk^0 + pk^1 + … + pk^ck)
欧几里得算法
//(最大公约数)
int gcd(int a, int b) {
if (b == 0) {
return a;
}
return gcd(b, a % b);
}
求欧拉函数
欧拉函数:小于或等于n的正整数中与n互质(公约数只有1)的数的数目
int phi(int x) {
int res = x;
for (int i = 2; i <= x / i; i++)
if (x % i == 0) {
res = res / i * (i - 1);
while (x % i == 0)
x /= i;
}
if (x > 1)
res = res / x * (x - 1);
return res;
}
筛法求欧拉函数
static int[] primes; // primes[]存储所有素数
static int[] euler; // 存储每个数的欧拉函数
static boolean[] st; // st[x]存储x是否被筛掉
void get_eulers(int n) {
int cnt = 0;
euler[1] = 1;
for (int i = 2; i <= n; i++) {
if (!st[i]) {
primes[cnt++] = i;
euler[i] = i - 1;
}
for (int j = 0; primes[j] <= n / i; j++) {
int t = primes[j] * i;
st[t] = true;
if (i % primes[j] == 0) {
euler[t] = euler[i] * primes[j];
break;
}
euler[t] = euler[i] * (primes[j] - 1);
}
}
}
扩展欧几里得算法
static class Int {
int v;
public Int() {}
}
// 求x, y,使得ax + by = gcd(a, b)
//c++可以利用指针交换值,java只能用内部类或者数组
int exgcd(int a, int b, Int x, Int y) {
if (b == 0) {
x.v = 1;
y.v = 0;
return a;
}
int d = exgcd(b, a % b, y, x);
y.v -= (a / b) * x.v;
return d;
}
递归法求组合数
for (int i = 0; i < N; i++) {
for (int j = 0; j <= i; j++) {
if (j == 0)
c[i][j] = 1;
else
c[i][j] = (c[i - 1][j] + c[i - 1][j - 1]) % mod;
}
}