题意:
给定 1≤N≤1e61 \le N \le 1e61≤N≤1e6 , 求满足 1x+1y=1N!\frac{1}{x} + \frac{1}{y} = \frac{1}{N!}x1+y1=N!1 的正整数有序对 (x,y)(x, y)(x,y) 的数量(模1e9+7)。
分析:
根据小学数学,变形式子:
N!(x+y)=xy N!(x + y) = xy N!(x+y)=xy
同时出现了 x+yx + yx+y 项和 xyxyxy 项,设法消去其中某一项。
构造:
(x−N!)(y−N!)=xy−N!(x+y)+(N!)2(x - N!)(y-N!) = xy -N!(x + y) + (N!)^2(x−N!)(y−N!)=xy−N!(x+y)+(N!)2
得出(x−N!)(y−N!)=(N!)2(x - N!)(y-N!) = (N!)^2(x−N!)(y−N!)=(N!)2
设 a=x−N!,b=y−N!a = x - N!, b = y - N!a=x−N!,b=y−N!,则转化为求有多少正整数有序对 (a,b)(a, b)(a,b) 满足 ab=(N!)2ab = (N!)^2ab=(N!)2。(证明:a,ba, ba,b 一定是正的。一个有趣的方法是类比电阻并联,题目中的式子可以理解为阻值为 xxx 的电阻与阻值为 yyy 的电阻并联,得到阻值为 N!N!N! 的总阻值。根据初中物理的结论,并联电阻总阻值小于任何一个支路的阻值,所以 x,y>N!x, y \gt N!x,y>N!, 即 a,b>0a, b \gt 0a,b>0。)
欧拉筛预处理 N!N!N! 的质因子集合 PPP,统计每个 pip_ipi 的贡献。得到唯一分解式 N!=∏piciN! = \prod p_i^{c_i}N!=∏pici,则 (N!)2=∏pi2ci(N!)^2 = \prod p_i^{2c_i}(N!)2=∏pi2ci。
若考虑无序对 (u,v)(u, v)(u,v), 对于每个质因子 pip_ipi, uuu 可选 [0,2ci][0, 2c_i][0,2ci] 种幂次,则 vvv 的幂次与 uuu 加起来为 2ci2c_i2ci,所以一个质因子 pip_ipi 有 2ci+12c_i + 12ci+1 种选法。一共有 ∏(2ci+1)\prod (2c_i + 1)∏(2ci+1) 个无序对,其中有一对有 u=vu = vu=v。所以有序对为 ∏(2ci+1)−12+1\frac{\prod (2c_i + 1) - 1}{2} + 12∏(2ci+1)−1+1 对。
代码:
#include <bits/stdc++.h>
using namespace std;
const int N_MAX = 1e6 + 10;
const long long mod = 1e9 + 7;
long long pf[N_MAX];
inline long long power(long long a, long long k = mod - 2) {
a %= mod;
long long ans = 1;
while (k) {
if (k & 1) ans = ans * a % mod;
a = a * a % mod;
k >>= 1;
}
return ans;
}
vector<int> prime;
int d[N_MAX];
long long N;
int main() {
cin >> N;
for (int i = 2; i <= N; i++) {
if (!d[i]) {
d[i] = i;
prime.push_back(i);
}
for (int j = 0; j < prime.size(); j++) {
if (prime[j] * i > N || prime[j] > d[i]) break;
d[prime[j] * i] = prime[j];
}
}
for (auto it : prime) {
long long dd = 1;
for (int i = 1; (dd *= it) <= N; i++) {
pf[it] += (N / dd);
}
// printf("%d: %lld\n", it, pf[it]);
}
long long ans = 1;
for (int i = 0; i < prime.size() ; i++) ans = (ans * (2LL * pf[prime[i]] + 1))% mod;
ans++;
ans = ans * power(2) % mod;
printf("%lld\n", ans);
}