题目大意
求 1 x + 1 y = 1 n \frac{1}{x}+\frac{1}{y}=\frac{1}{n} x1+y1=n1的解的个数
题目分析
其实就是化(luan)简(gao)
1
x
+
1
y
=
1
n
\frac{1}{x}+\frac{1}{y}=\frac{1}{n}
x1+y1=n1
y
x
y
+
x
x
y
=
1
n
\frac{y}{xy}+\frac{x}{xy}=\frac{1}{n}
xyy+xyx=n1
两边同乘xy得
x
+
y
=
x
y
n
x+y=\frac{xy}{n}
x+y=nxy
再同乘
−
n
-n
−n得
−
n
(
x
+
y
)
=
−
x
y
-n(x+y)=-xy
−n(x+y)=−xy
同时加上
n
2
n^2
n2得
n
2
−
n
(
x
+
y
)
=
n
2
−
x
y
n^2-n(x+y)=n^2-xy
n2−n(x+y)=n2−xy
去括号得
n
2
−
n
x
−
n
y
=
n
2
−
x
y
n^2-nx-ny=n^2-xy
n2−nx−ny=n2−xy
移项得
n
2
−
n
x
−
n
y
+
x
y
=
n
2
n^2-nx-ny+xy=n^2
n2−nx−ny+xy=n2
根据多项式的乘法化简左边的式子得
(
x
−
n
)
(
y
−
n
)
=
n
2
(x-n)(y-n)=n^2
(x−n)(y−n)=n2
化(luan)简(gao)完毕
对于每一个可能的(x-n),都必定会有一个(y-n)与其对应;而(x-n)是
n
2
n^2
n2的约数,去除重合的情况,问题转化成求
n
2
n^2
n2的约数的个数向上取整。
思考到这里,开心的你看了看题目数据,然后发现用(sang)心(xin)良(bing)苦(kuang)的出题人把数据出到了
1
0
14
10^{14}
1014。于是,O(n)求约数个数的办法被无情地否决了。
那我们应该怎么办呢?这时我们应该祭出一个定理——“唯一分解定理”!!!那么它是什么呢?
任 意 大 于 1 的 自 然 数 都 能 被 质 数 的 指 数 幂 的 乘 积 表 示 任意大于1的自然数都能被质数的指数幂的乘积表示 任意大于1的自然数都能被质数的指数幂的乘积表示
然并卵……
好了其实我们用到的其实是它的推论,准确地来说是
- 若 可 以 将 n 分 解 为 p 1 c 1 ∗ p 2 c 2 ∗ … ∗ p k c k ( n > 1 ) 若可以将n分解为p1^{c1}*p2^{c2}*…*pk^{ck}(n>1) 若可以将n分解为p1c1∗p2c2∗…∗pkck(n>1)
- 则 n 的 正 约 数 个 数 为 ( c 1 + 1 ) ∗ ( c 2 + 1 ) ∗ … ∗ ( c k + 1 ) 则n的正约数个数为(c1+1)*(c2+1)*…*(ck+1) 则n的正约数个数为(c1+1)∗(c2+1)∗…∗(ck+1)
它的原理就不在这里介绍了,我认为度娘会解释得很好的。
Code
#include<iostream>
#include<cstdio>
using namespace std;
long long ans=1,n;
int main(){
scanf("%lld",&n);//输入n
for(long long i=2,cnt=0;i*i<=n;i++){//唯一分解定理的推论
if(n%i==0){
long long cnt=0;
while(n%i==0)n/=i,++cnt;//求c的值
ans*=cnt*2+1;//直接乘上去
}
}
if(n>1) ans*=3;//假如n没有被除完,ans*=1*2+1,这里的代码是化简后的
ans=(ans+1)/2;//ans除以2向上取整
printf("%lld",ans);//输出
return 0;
}