預處理組合數
for (int i = 0; i <= N; ++i) {
c[i][0] = c[i][i] = 1;
for (int j = 1; j < i; ++j)
c[i][j] = (c[i - 1][j - 1] + c[i - 1][j]) % P;
}
擴展歐幾里得 ax + by = gcd(a, b)
LL exgcd(LL a, LL b, LL &x, LL &y) {
if (b == 0) {
x = 1;
y = 0;
return a;
}
LL r = exgcd(b, a % b, x, y);
LL tmp = x;
x = y;
y = tmp - a / b * y;
return r;
}
gcd(a, b) = gcd(b, a % b)
ax1 + by1 = gcd(a, b)
bx2 + (a % b)y2 = gcd(b, a % b)
a % b = a - a / b * b
ax1 + by1 = bx2 + ay2 - a / b * by2
ax1 + by1 = ay2 - b(x2 - a / b * y2)
x1 = y2
y1 = x2 - a / b * y2;
線性求逆元
void ready() {
inv[0] = inv[1] = 1;
for (int i = 2; i <= MaxNum; ++i) inv[i] = (P - P / i) * inv[P % i] % P;
}
i * inv[i] ≡ (P % i) * inv[P % i]≡ 1(mod P)
P % i = P - P / i * i
i * inv[i] ≡ P * inv[P % i] - P / i * i * inv[P % i] (mod P)
inv[i] ≡ -P / i * inv[P % i] (mod P)
inv[i] = (P - P / i) * inv[P % i] % P
中國剩餘定理
LL CRT(LL a[], LL m[], LL n) {
LL res = 0, M = 1, x, y;
for (int i = 0; i < n; ++i) M *= m[i];
for (int i = 0; i < n; ++i) {
LL Mi = M / m[i];
LL r = exgcd(Mi, m[i], x, y);
res = (res + Mi * x % M * a[i] % M + M) % M;
}
return res;
}
Miller-Rabin && pollard-rho
const int TIMES = 9;
LL mul_mod(LL a, LL b, LL P) {
LL res = 0;
a = a % P;
while (b) {
if (b & 1) {
res += a;
if (res > P) res -= P;
}
a <<= 1;
if (a > P) a -= P;
b >>= 1;
}
return res;
}
LL pow_mod(LL a, LL b, LL P) {
LL res = 1;
<span style="white-space:pre"> </span>a = a % P;
while (b) {
if (b & 1) res = mul_mod(res, a, P);
a = mul_mod(a, a, P);
b >>= 1;
}
return res;
}
bool Miller_Rabin(LL n, int times) { //Miller_Rabin(n, TIMES);
if (n == 2) return 1;
if (n < 2 || !(n & 1)) return 0;
LL b = n - 1;
int cnt = 0;
while ((b & 1) == 0) {
b >>= 1;
++cnt;
}
srand(time(NULL));
for (int i = 0; i < times; ++i) {
LL a = rand() % (n - 1) + 1;
LL x = pow_mod(a, b, n), y;
for (int j = 0; j < cnt; ++j) {
y = mul_mod(x, x, n);
if (y == 1 && x != 1 && x != n - 1) return 0;
x = y;
}
if (y != 1) return 0;
}
return 1;
}
LL factor[105];
int fac_cnt;
LL pollard_rho(LL n, int k) {
LL x, y, r, cnt = 1, cycle = 2;
srand(time(NULL));
x = rand() % (n - 1) + 1;
y = x;
while (1) {
++cnt;
x = (mul_mod(x, x, n) + k) % n;
r = __gcd(y - x, n);
if (1 < r && r < n) return r;
if (y == x) return n;
if (cnt == cycle) {
y = x;
cycle <<= 1;
}
}
}
void Find_Factor(LL n, int k) { //Find_Factor(n, 199);
if (n == 1) return;
if (Miller_Rabin(n, TIMES)) {
factor[fac_cnt++] = n;
return;
}
LL p = n;
while (p >= n) p = pollard_rho(p, --k);
Find_Factor(p, k);
Find_Factor(n / p, k);
}
待更新...