题目描述
求不定方程 (frac {1}{x} + frac{1}{y} = frac{1}{n!})的正整数解的个数
(n leq 100^6)
Solution
化简得
(x * n! + y * n! = x * y)
(x * y - x * n! - y *n! +(n!)^2 = (n!)^2)
((x - n!)(y - n!) = (n!)^2)
以上,我们可以看出,所求正整数解的个数其实就是((n!)^2)的约数的个数。
这个当然可以暴力求,但是很慢。考虑一个质数p在n!中出现的次数,显然是(frac{n}{p}),这既表示n中包含几个p,同时也能说明小于等于n的数中,有多少个是p的倍数。同理(p^2)在n!中出现的次数是(frac{n}{p^2}),以此类推,最后将这些全部加起来就是p在n!阶乘中出现的次数。在应用因子个数公式即可。
for(int i = 1; pri[i] <= n; ++i){
int tot = 0, x = n, y = pri[i];
while(x) tot += x / y, x /= y;
ans = (ans * (tot << 1 | 1) % mod) % mod;//之所以要<<1是因为是n!*n!
}
举个例子或许好理解。
13!中有多少个3?包含3这个因数的数有:3, 6, 9, 12,分别包含1, 1, 2, 1个3,总数就是5个。而13 / 3 = 4, 4 / 3 = 1, 4 + 1 = 5。
Code
#include <iostream>
#include <cstdio>
using namespace std;
inline long long read() {
long long x = 0; int f = 0; char c = getchar();
while (c < '0' || c > '9') f |= c == '-', c = getchar();
while (c >= '0' && c <= '9') x = (x << 1) + (x << 3) + (c ^ 48), c = getchar();
return f? -x:x;
}
const int mod = 1e9 + 7;
int n, pri[1000006], cnt;
long long ans = 1;
bool v[1000006];
inline void get_pri() {
for (int i = 2; i <= 1000000; ++i) {
if (!v[i]) pri[++cnt] = i;
for (int j = 1; j <= cnt && pri[j] * i <= n; ++j) {
v[pri[j] * i] = 1;
if (i % pri[j] == 0) break;
}
}
}
int main() {
n = read();
get_pri();
for (int i = 1; pri[i] <= n; ++i) {
int tot = 0, x = n, y = pri[i];
while (x) tot += x / y, x /= y;
ans = (ans * (tot << 1 | 1) % mod) % mod;
}
printf("%lld
", ans);
return 0;
}