分析
看到这么个窒息的式子,难道不想化简吗?
1
x
+
1
y
=
1
n
\dfrac{1}{x}+\dfrac{1}{y}=\dfrac{1}{n}
x1+y1=n1
n
(
x
+
y
)
=
x
y
n(x+y)=xy
n(x+y)=xy
n
x
+
n
y
=
x
y
nx+ny=xy
nx+ny=xy
x
y
−
n
x
=
n
y
xy-nx=ny
xy−nx=ny
x
(
y
−
n
)
=
n
y
x(y-n)=ny
x(y−n)=ny
x
=
n
y
y
−
n
x=\dfrac{ny}{y-n}
x=y−nny
诶还是没有什么用啊。
那么不妨换元,设
a
=
y
−
n
a=y-n
a=y−n
则
y
=
a
+
n
y=a+n
y=a+n
x
=
n
(
a
+
n
)
a
x=\dfrac{n(a+n)}{a}
x=an(a+n)
x
=
n
+
n
2
a
x=n+\dfrac{n^2}{a}
x=n+an2
诶,对于每个
a
a
a,都有对应的一对
x
,
y
x,y
x,y,那
a
a
a是什么啊?
诶对,是
n
2
n^2
n2的因子……什么?难道枚举
n
2
n^2
n2的因子吗???看着
1
e
9
1e9
1e9的
n
n
n,我不禁陷入了沉思……
诶我可以枚举
n
n
n的因子啊,那只要到
n
\sqrt{n}
n就可以了吧(大雾),于是WA得很惨烈。
咋回事?很简单,4是36的因子,但是在枚举6的因子时没有算。
所以这里写一个能算
n
p
n^p
np的因子数的方法:分解质因数。对于一个
n
n
n,根据唯一分解定理,一定可以写成
p
1
i
1
∗
p
2
i
2
∗
p
3
i
3
.
.
.
.
.
.
p
m
i
m
p_1^{i_1}*p_2^{i_2}*p_3^{i_3}......p_m^{i_m}
p1i1∗p2i2∗p3i3......pmim,
p
p
p为质数。
所以每个质因子都可以选
0
,
1
,
2...
,
i
0,1,2...,i
0,1,2...,i个,所以因子总数就是每个质因子个数的乘积。
所以只要素数筛,统计每个质因子个数为 i i i, n p n^p np中就有 i ∗ p i*p i∗p个该因子,加上一个选 0 0 0的可能,这个因子可以选到 i ∗ p + 1 i*p+1 i∗p+1个。
而筛的时候只要枚举到 n \sqrt{n} n, n n n除完了之后,剩下的就是大质数,再处理就可以了。
最后算出了 n 2 n^2 n2的因子数,由于 x ≤ y x\le y x≤y所以有序,要除以 2 2 2,但是, n ∗ n n*n n∗n不能除2,因为只算了一遍。故最后答案是 c n t + 1 2 \dfrac{cnt+1}{2} 2cnt+1。
代码
#include<bits/stdc++.h>
#define ll long long
#define inf 1<<30
using namespace std;
const int MAXN=1e5+10;
int p[MAXN];
int main()
{
ll n,ans=1;
scanf("%lld",&n);
for(int i=2;i*i<=n;i++){
if(p[i]) continue;
for(int j=i*2;j*j<=n;j+=i) p[j]=1;
if(n%i==0){
ll cnt=0;
while(n%i==0) n/=i,cnt++;
ans=ans*(cnt*2ll+1);
}
}
if(n!=1) ans*=3ll;//大质数
printf("%lld\n",(ans+1)/2);
}