描述
题解
这道数论题挺讲究技巧的,需要先通过原公式推出 N!^2 = (X - N!) * (Y - N!)
,所以我们只需要求 N!^2 的约数个数。又因为 N!^2 = (p1^a1)^2 * (p2^a2)^2 * … * (pm^am)^2
,所以我们只需要求出 2 * a1、2 * a2、2 * a3、…、2 * am,那么我们就需要求小于等于 N 的素数,然后对 1 ~ N (因为我们只需要求a1、a2、a3、…、am即可,这个与 1~N 有关)每个数进行质因数分解。因为题目中要求0 < x <= y
,所以,最后结果为(1 + Π(2 * ai + 1)) / 2
,最最后注意除法取模要用到逆元。挺有趣的一道问题……
代码
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long ll;
const int MAXN = 1e6 + 10;
const int MOD = 1e9 + 7;
int vis[MAXN];
/* * 素数筛选,查找出小于等于MAXN的素数 * prime[0]存素数的个数 */
int prime[MAXN + 1];
void getPrime()
{
memset(prime, 0, sizeof(prime));
for (int i = 2; i <= MAXN; i++)
{
if (!prime[i])
{
prime[++prime[0]] = i;
}
for (int j = 1; j <= prime[0] && prime[j] <= MAXN / i; j++)
{
prime[prime[j] * i] = 1;
if (i % prime[j] == 0)
{
break;
}
}
}
}
ll qPow(ll a, ll n)
{
ll ans = 1;
while (n)
{
if (n & 1)
{
ans = ans * a % MOD;
}
a = a * a % MOD;
n >>= 1;
}
return ans;
}
int main()
{
getPrime();
int n;
cin >> n;
memset(vis, 0, sizeof(vis));
for (int i = 1; i <= n; i++)
{
int k = i;
for (int j = 1; j <= prime[0] && prime[j] * prime[j] <= k; j++)
{
if (k % prime[j] == 0)
{
while (k % prime[j] == 0)
{
k /= prime[j];
vis[prime[j]] += 2;
}
}
}
if (k != 1)
{
vis[k] += 2;
}
}
ll ans = 1;
for (int i = 0; i <= MAXN; i++)
{
ans = ans * (vis[i] + 1) % MOD;
}
cout << (ans + 1) * qPow(2LL, MOD - 2) % MOD << endl;
return 0;
}