給定整數 n 和 k(0 ≤ k ≤ n ≤ 431),求組合數 C(n, k) 的不同約數個數。結果保證不超過 263−1。
若正整數 N 的質因子分解為 N = p1a1 × p2a2 × … × psas,則其約數個數公式為:
T(N) = (a1+1)(a2+1)…(as+1)
對於組合數 C(n, k) = n! / (k! × (n−k)!),其質因子 p 的指數可通過勒讓德公式計算:
e(p) = ⌊n/p⌋ + ⌊n/p2⌋ + ⌊n/p3⌋ + …
則 C(n, k) 中質因子 p 的指數為 e(n) − e(k) − e(n−k)。
#include <cstdio>
#include <cstring>
using namespace std;
typedef long long LL;
const int MAXN = 431;
int prime[1010], pn = 0;
LL cnt[MAXN+1][MAXN+1];
void sieve() {
bool vis[MAXN+1] = {0};
for (int i = 2; i <= MAXN; ++i) {
if (!vis[i]) prime[pn++] = i;
for (int j = 0; j < pn && i * prime[j] <= MAXN; ++j) {
vis[i * prime[j]] = true;
if (i % prime[j] == 0) break;
}
}
}
void precompute() {
sieve();
for (int i = 2; i <= MAXN; ++i) {
for (int j = 0; j < pn && prime[j] <= i; ++j) {
int p = prime[j], t = i, sum = 0;
while (t) { t /= p; sum += t; }
cnt[i][p] = sum;
}
}
}
int main() {
precompute();
LL n, k;
while (scanf("%lld %lld", &n, &k) == 2) {
LL ans = 1;
for (int i = 0; i < pn && prime[i] <= n; ++i) {
int p = prime[i];
LL e = cnt[n][p] - cnt[k][p] - cnt[n-k][p];
ans *= (e + 1);
}
printf("%lld\n", ans);
}
return 0;
}
預處理 O(N log log N + N × π(N)),單次查詢 O(π(n)),完全滿足題目限制。