题意概括:
题目意思很明白,输入一个 i n t int int类型整数 n n n ( 1 < = n < = 1 0 6 1<=n<=10^6 1<=n<=106 ) 求方程 1 x + 1 y = 1 n ! \frac{1}{x}+\frac{1}{y}=\frac{1}{n!} x1+y1=n!1 ( n ! n! n! 表示 n n n 的阶乘,即 n ! = 1 × 2 × 3 × ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ × n n!=1\times2\times3\times······\times n n!=1×2×3×⋅⋅⋅⋅⋅⋅×n ) 解的个数
题目分析:
肯定是一个数论题~~(废话)~~,题目中的方程直接枚举是
O
(
n
3
)
O(n^3)
O(n3) 的时间复杂度,绝对会
T
L
E
TLE
TLE ,那么就对方程进行分析:
1
x
+
1
y
=
1
n
!
设
n
!
=
k
,
\begin{aligned} & \frac{1}{x} + \frac{1}{y} = \frac{1}{n!}\\ & 设 n!=k,\\ \end{aligned}
x1+y1=n!1设n!=k,
第一眼看上去,
x
x
x 和
y
y
y 都是一次的整数,只有
n
!
n!
n! 是一个式子,所以用一个未知数代替,方便运算和思考。其实就是我懒对原方程进行化简,我习惯把
x
x
x 当作主元,用
y
y
y 也可以。把
y
y
y 和
k
k
k 当作一个常数,用解普通方程的步骤去解。
∴
1
x
+
1
y
=
1
k
1
x
=
1
k
−
1
y
1
x
=
y
k
y
−
k
k
y
1
x
=
y
−
k
k
y
x
=
k
y
y
−
k
\begin{aligned} & \therefore \frac{1}{x} + \frac{1}{y} = \frac{1}{k}\\ & \frac{1}{x} = \frac{1}{k} - \frac{1}{y}\\ & \frac{1}{x} = \frac{y}{ky} - \frac{k}{ky}\\ & \frac{1}{x} = \frac{y-k}{ky}\\ & x = \frac{ky}{y-k}\\ \end{aligned}
∴x1+y1=k1x1=k1−y1x1=kyy−kykx1=kyy−kx=y−kky
这时,无法对方程继续化简,但分式上下都有
y
y
y 和
k
k
k ,所以可以考虑再设一个关于
y
y
y 和
k
k
k 的未知数,去表达
y
y
y 和
k
k
k 的关系。
设
y
−
k
=
p
,
∴
y
=
k
+
p
\begin{aligned} & 设 y-k = p,\\ & \therefore y = k + p\\ \end{aligned}
设y−k=p,∴y=k+p
找到之后,就可以把
y
=
k
+
p
y=k+p
y=k+p 代入方程,得到
∴
x
=
k
(
k
+
p
)
p
∴
x
=
k
+
k
2
p
\begin{aligned} & \therefore x = \frac{k(k+p)}{p}\\ & \therefore x = k+\frac{k^2}{p}\\ \end{aligned}
∴x=pk(k+p)∴x=k+pk2
解出
x
x
x 的值后,观察式子,发现可以运用文化课上讲过的整数的性质,
∵
x
,
k
=
n
!
为正整数
∴
p
∣
k
2
∴
y
−
n
!
∣
(
n
!
)
2
∴
(
y
−
n
!
)
为
(
n
!
)
2
的因子
∴
(
y
−
n
!
)
为
n
!
的因子
∵
y
,
n
!
为正整数
∴
x
为正整数
∴
只要
(
y
−
n
!
)
为
n
!
的因子,就有原方程的一组解
\begin{aligned} & \because x,k=n!为正整数\\ & \therefore p \mid k^2\\ & \therefore y-n! \mid (n!)^2\\ & \therefore (y-n!) 为(n!)^2的因子\\ & \therefore (y-n!) 为n!的因子\\ & \because y,n!为正整数\\ & \therefore x为正整数\\ & \therefore 只要(y-n!)为n!的因子,就有原方程的一组解\\ \end{aligned}
∵x,k=n!为正整数∴p∣k2∴y−n!∣(n!)2∴(y−n!)为(n!)2的因子∴(y−n!)为n!的因子∵y,n!为正整数∴x为正整数∴只要(y−n!)为n!的因子,就有原方程的一组解
通过分析,就可以把原问题转化为求
n
!
n!
n!的因子数
代码实现
由唯一分解定理,我们只需要解出n!的质因数,balabala的一个埃氏筛函数
int primes[1000005];//记录质因数
bool st[1000005];//标记是否为质数
int cnt;
int n;
long long ans=1;
void prime_set(int n){
st[1]=1;
for (int i=2;i<=n;i++){
if (!st[i])
primes[++cnt]=i;
for (int j=1;j<=cnt&&primes[j]*i<=n;j++){
st[primes[j]*i]=1;
if (i%primes[j]==0){
break;
}
}
}
}
通过唯一分解定理的另一个公式,即
n
的因子数
=
∏
i
=
0
质因子个数
质因子
i
的个数
+
1
n的因子数=\prod\limits_{i=0}^{质因子个数}质因子i的个数+1
n的因子数=i=0∏质因子个数质因子i的个数+1
就可以得到答案了
prime_set(n);
for (int i = 1; i <= cnt; i++){
int s = 0;
for (int j=n;j;j/=primes[i]){
s+=j/primes[i];
}
ans=1ll*ans*(s<<1|1)%P;//1ll用来防止数据溢出
}
printf("%lld",ans);
Code
#include<bits/stdc++.h>
#define P 1000000007
using namespace std;
int primes[1000005];
bool st[1000005];
int cnt;
int n;
long long ans=1;
void prime_set(int n){
st[1]=1;
for (int i=2;i<=n;i++){
if (!st[i])
primes[++cnt]=i;
for (int j=1;j<=cnt&&primes[j]*i<=n;j++){
st[primes[j]*i]=1;
if (i%primes[j]==0){
break;
}
}
}
}
int main(){
scanf("%d",&n);
prime_set(n);
for (int i = 1; i <= cnt; i++){
int s = 0;
for (int j=n;j;j/=primes[i]){
s+=j/primes[i];
}
ans=1ll*ans*(s<<1|1)%P;
}
printf("%lld",ans);
return 0;
}