analysis
首先先得化简式子,因为这个式子确实看不出来什么
一般看到的题解里有这两种化法:
1.
1
x
+
1
y
=
1
n
!
\frac{1}{x}+\frac{1}{y}=\frac{1}{n!}
x1+y1=n!1
x
y
x
+
y
=
n
!
\frac{xy}{x+y}=n!
x+yxy=n!
x
y
=
n
!
(
x
+
y
)
xy=n!(x+y)
xy=n!(x+y)
−
n
!
(
x
+
y
)
+
x
y
=
0
←
→
(
n
!
x
+
n
!
y
)
−
x
y
=
0
-n!(x+y)+xy=0\leftarrow\rightarrow(n!x+n!y)-xy=0
−n!(x+y)+xy=0←→(n!x+n!y)−xy=0
对数学敏感的同学相信写到这一步时就已经可以发现一些东西了,这个式子是十字相乘法拆开括号的后两项!
若
设
a
=
−
n
!
,
b
=
x
,
c
=
y
,
则
a
(
b
+
c
)
+
b
c
=
0
,
等
式
两
边
同
时
加
上
a
2
若设a=-n!,b=x,c=y,则a(b+c)+bc=0,等式两边同时加上a^2
若设a=−n!,b=x,c=y,则a(b+c)+bc=0,等式两边同时加上a2
则
a
2
+
a
(
b
+
c
)
+
b
c
=
0
,
(
a
+
c
)
(
a
+
b
)
=
0
则a^2+a(b+c)+bc=0,(a+c)(a+b)=0
则a2+a(b+c)+bc=0,(a+c)(a+b)=0
于是有
(
x
−
n
!
)
(
y
−
n
!
)
=
(
n
!
)
2
(x-n!)(y-n!)=(n!)^2
(x−n!)(y−n!)=(n!)2
也就是说
(
x
−
n
!
)
∣
(
n
!
)
2
(x-n!)|(n!)^2
(x−n!)∣(n!)2
那么,
(
x
−
n
!
)
(x-n!)
(x−n!)等价于
(
n
!
)
2
(n!)^2
(n!)2的因子,又由于
(
x
−
n
!
)
(x-n!)
(x−n!)和x的个数相等,那么x的个数和
(
n
!
)
2
(n!)^2
(n!)2的因子的个数一一对应
2.
设
y
=
n
!
+
k
设y=n!+k
设y=n!+k(至于为什么要这样构造,我也不知道啊)
则原方程为
x
(
n
!
+
k
)
=
n
!
(
x
+
(
n
!
+
k
)
)
x(n!+k)=n!(x+(n!+k))
x(n!+k)=n!(x+(n!+k))
即
x
n
!
+
x
k
=
n
!
(
x
+
n
!
+
k
)
,
x
n
!
+
x
k
=
n
!
x
+
(
n
!
)
2
+
n
!
k
即xn!+xk=n!(x+n!+k),xn!+xk=n!x+(n!)^2+n!k
即xn!+xk=n!(x+n!+k),xn!+xk=n!x+(n!)2+n!k
也
就
是
x
=
(
n
!
)
2
k
+
n
!
也就是x=\frac{(n!)^2}{k}+n!
也就是x=k(n!)2+n!
也
就
是
说
x
的
个
数
等
于
(
n
!
)
2
的
因
子
的
个
数
也就是说x的个数等于(n!)^2的因子的个数
也就是说x的个数等于(n!)2的因子的个数
那么本题就是求
(
n
!
)
2
(n!)^2
(n!)2的因子的个数
求因子个数,根据唯一分解定理的推论:
x
=
p
1
s
1
×
p
2
s
2
×
.
.
.
.
.
.
p
n
s
m
=
∏
i
=
1
m
p
i
s
i
,
p
i
是
素
数
x=p_1^{s1}\times p_2^{s_2}\times......p_n^{s_m}=\prod_{i=1}^{m}p_i^{s_i},p_i是素数
x=p1s1×p2s2×......pnsm=∏i=1mpisi,pi是素数
x
的
约
数
个
数
d
(
n
)
=
∏
i
=
1
m
(
s
i
+
1
)
x的约数个数d(n)=\prod_{i=1}^{m}(s_i+1)
x的约数个数d(n)=∏i=1m(si+1)根据乘法原理可证明
code
对 ( n ! ) 2 (n!)^2 (n!)2唯一分解的时候,最暴力的做法是直接分解,也就是对每一个n,枚举每个小于 n \sqrt n n的质数,时间复杂度为 O ( n × n ) O(\sqrt n \times n) O(n×n),不知为什么居然还在评测机上跑过了
#include<bits/stdc++.h>
using namespace std;
#define loop(i,start,end) for(register int i=start;i<=end;++i)
#define anti_loop(i,start,end) for(register int i=start;i>=end;--i)
#define clean(arry,num) memset(arry,num,sizeof(arry))
#define isdegit(a) ((a>='0'&&a<='9'))
#define ll long long
const ll mod=1e9+7;
template<typename T>void read(T &x){
x=0;char r=getchar();T neg=1;
while(!isdegit(r)){if(r=='-')neg=-1;r=getchar();}
while(isdegit(r)){x=(x<<1)+(x<<3)+r-'0';r=getchar();}
x*=neg;
}
const int maxn=1e6;
ll prime[maxn],nfp=0;
ll v[maxn];
inline void shai(int n){
clean(prime,0);
clean(v,0);
nfp=0;
loop(i,2,n){
if(!v[i]){
v[i]=i;
prime[++nfp]=i;
}
loop(j,1,nfp){
if(i*prime[j]>n||v[i]<prime[j])
break;
v[prime[j]*i]=prime[j];
}
}
}
ll fj[maxn];
inline void fenjie(ll a){
loop(i,1,nfp){
if(prime[i]*prime[i]>a) break;
if(a%prime[i]==0){
while(a%prime[i]==0){
a/=prime[i];
++fj[i];
}
}
}
if(a==1) return;
int mark=lower_bound(prime+1,prime+1+nfp,a)-prime;
++fj[mark];
}
int n;
int main(){
#ifndef ONLINE_JUDGE
freopen("datain.txt","r",stdin);
#endif
read(n);
shai(n);
loop(i,2,n){
fenjie((ll)i);
}
ll res=1;
for(register int i=1;fj[i]!=0;++i){
res=(res*(fj[i]<<1|1))%mod;
}
printf("%lld\n",res);
return 0;
}
但是我们不需要那么暴力
可以利用线性筛里面处理出来的数组v(v[i]是i的最小质因子)来加快我们对于每一个数唯一分解的速度
对于一个数,我们可以每次除去它的最小质因子,并且累加记录,然后对于计算后得到的结果继续除其最小质因子,直到把这个数除成1为止
这样的话,时间复杂度降为
O
(
n
l
o
g
n
)
O(nlogn)
O(nlogn),这样就可以过了(至于为什么每个数的质因子个数为logn,我不知道)
#include<bits/stdc++.h>
using namespace std;
#define loop(i,start,end) for(register int i=start;i<=end;++i)
#define anti_loop(i,start,end) for(register int i=start;i>=end;--i)
#define clean(arry,num) memset(arry,num,sizeof(arry))
#define isdegit(a) ((a>='0'&&a<='9'))
#define ll long long
const ll mod=1e9+7;
template<typename T>void read(T &x){
x=0;char r=getchar();T neg=1;
while(!isdegit(r)){if(r=='-')neg=-1;r=getchar();}
while(isdegit(r)){x=(x<<1)+(x<<3)+r-'0';r=getchar();}
x*=neg;
}
const int maxn=1e6;
ll prime[maxn],nfp=0;
ll v[maxn];
inline void shai(int n){
clean(prime,0);
clean(v,0);
nfp=0;
loop(i,2,n){
if(!v[i]){
v[i]=i;
prime[++nfp]=i;
}
loop(j,1,nfp){
if(i*prime[j]>n||v[i]<prime[j])
break;
v[prime[j]*i]=prime[j];
}
}
}
ll fj[maxn];
int n;
int main(){
#ifndef ONLINE_JUDGE
freopen("datain.txt","r",stdin);
#endif
read(n);
shai(n);
loop(i,1,n){
for(int j=i;j!=1;j/=v[j]){
++fj[v[j]];
fj[v[j]]%=mod;
}
}
ll res=1;
for(register int i=1;i<=n;++i){
res=(res*(fj[i]<<1|1))%mod;
}
printf("%lld\n",res);
return 0;
}