解题思路
由原题的式子可推出:
y
=
x
n
!
x
−
n
!
y=\frac{xn!}{x-n!}
y=x−n!xn!,我们设
t
=
x
−
n
!
t=x-n!
t=x−n!,则
x
=
t
+
n
!
x=t+n!
x=t+n!,得到
y
=
n
!
+
(
n
!
)
2
t
y=n!+\frac{(n!)^2}{t}
y=n!+t(n!)2,因为n和y是整数,所以t一段要是
(
n
!
)
2
(n!)^2
(n!)2的约数,题目就变成了求
(
n
!
)
2
(n!)^2
(n!)2的约数个数,即求
∏
i
=
1
m
(
c
i
+
1
)
∏_{i=1}^m(c_i+1)
∏i=1m(ci+1)
对于一个合数n^2,它的约数个数为
∏
i
=
1
m
(
c
i
∗
2
+
1
)
∏_{i=1}^m(c_i*2+1)
∏i=1m(ci∗2+1),所以首先求n中的质数个数,然后求出所有的质数在n!中出现的次数,
最后通过 ∏ i = 1 m ( c i ∗ 2 + 1 ) ∏_{i=1}^m(c_i*2+1) ∏i=1m(ci∗2+1)得到 ( n ! ) 2 (n!)^2 (n!)2的约数个数。
代码
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<iomanip>
#include<cstring>
#include<cmath>
#include<map>
#include<queue>
#define ll long long
#define ldb long double
using namespace std;
const ll mod=1e9+7;
ll n,p,cnt,pri[10000010],v[10000010],c[10000010],ans=1;
int main(){
scanf("%lld",&n);
for(ll i=2;i<=n;i++)
{
if(!v[i])
{
v[i]=i;
pri[++cnt]=i;
}
for(ll j=1;j<=cnt;j++)
{
if(pri[j]>v[i]||pri[j]>n/i)break;
v[pri[j]*i]=pri[j];
}
}
for(ll i=1;i<=cnt;i++)
{
for(ll j=pri[i];j<=n;j*=pri[i])
{
c[i]+=n/j;
c[i]%=mod;
}
}
for(int i=1;i<=cnt;i++)
ans=ans*((2*c[i]+1)%mod)%mod;
printf("%lld",ans);
}