利用算術基本定理(唯一分解定理):任意整數 > 1 可唯一分解為質因子乘積。將分子分母分解為質因子指數向量,相減判斷是否為整數。
對於分數 E = (X₁×X₃×...×Xₖ) / X₂:
C(p,q)/C(r,s) = [p! × s! × (r-s)!] / [q! × (p-q)! × r!] 分子質因子指數 +1,分母 -1 最後正指數相乘,負指數相除(邊乘邊除防溢出) 保留 5 位小數輸出
const int MAXN = 10005;
int prime[MAXN], pn;
bool vis[MAXN];
void sieve(int n) {
int m = sqrt(n);
for (int i = 2; i <= m; i++)
if (!vis[i])
for (int j = i*i; j <= n; j += i)
vis[j] = 1;
for (int i = 2; i <= n; i++)
if (!vis[i]) prime[pn++] = i;
}
// n! 的質因子指數加 d (d=+1 或 -1)
void add_factorial(int n, int d) {
for (int i = 0; i < pn && prime[i] <= n; i++) {
int p = prime[i], cnt = 0;
for (int m = n; m; m /= p) cnt += m / p;
exp[p] += cnt * d;
}
}
// C(p,q)/C(r,s)
memset(exp, 0, sizeof(exp));
add_factorial(p, 1); add_factorial(q, -1); add_factorial(p-q, -1);
add_factorial(r, -1); add_factorial(s, 1); add_factorial(r-s, 1);
double ans = 1;
for (int i = 0; i < pn; i++) {
if (exp[prime[i]] > 0)
for (int j = 0; j < exp[prime[i]]; j++) ans *= prime[i];
else if (exp[prime[i]] < 0)
for (int j = 0; j < -exp[prime[i]]; j++) ans /= prime[i];
}
printf("%.5f\n", ans);
n/p + n/p² + ... 公式,O(log_p n)