思路:
首先将方程左边通分:
然后十字相乘:
看到这里就有点因式分解分味道了,我们再给两边同时加上,然后分解因式得到:
令a=x-n!,b=y-n!,c=,那么a*b=c 的求a,b有多少组解,由于n! 为确定的,a,b有多少不同的解就代表了x,y有多少不同的解。
可行性:
约数个数定理:
定理的证明大家可以自己查。
首先我们是要对进行质因子分解。
我们设 =
那么 =
所以按照定理答案就是: (2c1+1)(2c2+1)...(2ck+1)
再一个问题就是我们如何对 n! 进行质因子分解, n!太大我们无法存储。
n!=n*(n-1)*(n-2)*···*3*2*1
所以我们可以分别对n,(n-1),(n-2),...3,2,1各进行质因子分解。
TIPS:
进行质因数分解,所以先来一遍素数筛,由于数据量很大,会有卡埃氏筛,所以记得用欧拉线性筛!
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN=1e6+7;
const int mod=1e9+7;
int n,cnt,primes[MAXN];
bool vis[MAXN];
unordered_map<int,int> p;
void getprime()//欧拉筛
{
for(int i=2;i<=n/i;i++)
{
if(!vis[i]) primes[++cnt]=i;
for(int j=1;j<=cnt&&i*primes[j]<n;j++)
{
vis[i*primes[j]]=1;
if(i%primes[j]==0) break;
}
}
}
int main()
{
cin>>n;
getprime();
for(int i=2,x;i<=n;i++)//n!的质因子分解
{
x=i;
for(int j=1;j<=cnt&&primes[j]*primes[j]<=i;j++)
{
while(x%primes[j]==0)
{
p[primes[j]]++;
x/=primes[j];
}
}
if(x>1) p[x]++;
}
ll ans=1;
for(auto x=p.begin();x!=p.end();x++)//统计答案
{
ans=ans*(x->second*2+1)%mod;
}
cout<<ans;
return 0;
}