题目链接:[Violet]樱花 - 洛谷
分析:原方程两边同时乘以x*y*(n!)得n!(x+y)=x*y,两边同时加上(n!)^2并减去n!(x+y)得 (n!)^2=(n!)^2-n!(x+y)+x*y,仔细观察等式右面可以发现其等于(n!-x)*(n!-y),那么方程就转换为了
(n!-x)*(n!-y)=(n!)^2
题目中说的是求正整数解,如果x<=n!由于x和y是正数,那么就有n!>(n!-x)>=0,那么n!>(n!-y)>=0,显然是无解的,两个小于n!的数乘积不可能大于(n!)^2,所以有x和y均大于n!
也就是(x-n!)*(y-n!)=(n!)^2
有了这个等式我们就能发现(x-n!)和(y-n!)分别是(n!)^2的两个因子,那么求x,y的整数解就变成了求(n!)^2的因子个数,不知道如何求一个数因子个数的小伙伴可以看这里:因子个数及因子之和问题_AC__dream的博客-CSDN博客_因子数之和
我们直接求出来2~n的每个数含有的质因子及其次幂即可,最后只需要把次幂乘以2即可得到n^2含有的质因子及其次幂
下面是代码:
#include<cstdio>
#include<iostream>
#include<cstring>
#include<vector>
#include<algorithm>
#include<map>
#include<cmath>
#include<queue>
using namespace std;
const int N=1e6+10,mod=1e9+7;
int prime[N],cnt,ans[N];
bool vis[N];
void init()
{
for(int i=2;i<N;i++)
{
if(!vis[i]) prime[++cnt]=i;
for(int j=1;j<=cnt&&i*prime[j]<N;j++)
{
vis[i*prime[j]]=true;
if(i%prime[j]==0) break;
}
}
}
int main()
{
int n;
init();
cin>>n;
// for(int i=1;i<=cnt;i++) printf("%d\n",prime[i]);
for(int i=2;i<=n;i++)
{
int t=i;
for(int j=1;prime[j]*prime[j]<=i;j++)
while(t%prime[j]==0)
{
ans[j]+=1;
t/=prime[j];
}
if(t!=1)
ans[(lower_bound(prime+1,prime+cnt+1,t)-prime)]++;//找到t对应的素数下标并将答案计入
}
long long sum=1;
for(int i=1;i<=cnt;i++)
if(ans[i])
sum=sum*(ans[i]*2+1)%mod;
cout<<sum;
return 0;
}