传送门
题意: 1/x + 1/y = 1/n! 求这个等式的正整数解(x, y) 有多少对.
思路: 我们首先令n! = z, 那么原式就等于 1/x + 1/y = 1/z, 化简的 xz + yz = xy –> xz + yz - xy + z^2 = z^2,
就等于 (z-x)(z-y) = z^2, 很明显这个方程的解就是z^2的约数个数, 比如n = 2时, 就变成了4 = (2-x)(2-y), 变换一下就为4 = (x-2)(y-2), 很明显4有3个约数1, 2, 4, 所以我们每个相对应的带入进去解出x, y即可, 比如代入1时, x = 3, y = 6, 依次进行就是, 现在就是如何求(n!)^2的约数个数了? 首先 一个数的平方的约数个数很好求, 通过约数个数定理推导可知为(k*cnt1+1)*(k*cnt2+1)….., cnt1, 2分别时这个数的素数因子的个数, 那么问题就变成了如何快速的求n!的一些素数因子的个数,
当然我们方便的求也可以反向求就一直用n/=p即可, 到此可解决此问题.
AC Code
const int maxn = 1e6+5;
int pri[maxn]; bool ispri[maxn];
void init(int n) {
int k = 0; Fill(ispri, true); ispri[1] = false;
for (int i = 2 ; i <= n ; i ++) {
if (ispri[i]) {
pri[++k] = i;
for (int j = i+i ; j <= n ; j += i)
ispri[j] = false;
}
}
pri[0] = k;
}
int cal(int n, int m) {
int res = 0;
while(n) res += n /= m;
return res;
}
void solve() {
int n; scanf("%d", &n);
ll ans = 1; init(n);
for (int i = 1 ; i <= pri[0] && pri[i] <= n ; i ++) {
(ans *= (2*cal(n, pri[i])+1)) %= mod;
}
printf("%lld\n", ans);
}