给定 n n n,求有多少四元组 ( a , b , c , d ) (a,b,c,d) (a,b,c,d)满足 a b = c d a^b=c^d ab=cd
从唯一分解看,幂
b
,
d
b,d
b,d只改变质因数的幂,而不改变质因数的种数,因此,要满足题意,
a
,
c
a,c
a,c一定存在结构一样的部分,设为
x
x
x,那么
a
=
x
k
1
c
=
x
k
2
a=x^{k_{1}}\\ c=x^{k_{2}}
a=xk1c=xk2
对 x = 1 x=1 x=1, b , d b,d b,d不一定一样,且都任意取值,方案数为 n 2 n^2 n2,此时为 a = c = 1 a=c=1 a=c=1;
对 a = c ≠ 1 a=c\neq1 a=c=1时, a = c ∈ [ 2 , n ] a=c\in[2,n] a=c∈[2,n], b = d ∈ [ 1 , n ] b=d\in[1,n] b=d∈[1,n],方案数为 n ( n − 1 ) n(n-1) n(n−1)
下面只需要考虑 a ≠ c a\neq c a=c的情况
当我们知道同样部分
x
x
x的时候,我们很容易可以知道以这个数为最小结构的数有多少,而我们只需要枚举一个最小的
x
x
x,就可以统计所有以
x
x
x为最小结构的数,他们分别是
x
,
x
2
,
x
3
,
.
.
.
.
x,x^2,x^3,....
x,x2,x3,....
此时只需要找出序列长度大于
2
2
2的
x
x
x,即
x
2
≤
n
⇒
x
≤
n
x^2\leq n\Rightarrow x\leq\sqrt{n}
x2≤n⇒x≤n,我们用
O
(
n
)
O(\sqrt{n})
O(n)枚举
x
x
x,只需要找出最大的
i
i
i满足
x
i
≤
n
x^i\leq n
xi≤n,即可找出这些数,那么
a
,
c
a,c
a,c一定出现在这些数之中,原题要满足
x
b
k
1
=
x
d
k
2
⇒
b
k
1
=
d
k
2
x^{bk_{1}}=x^{dk_{2}}\Rightarrow bk_{1}=dk_{2}
xbk1=xdk2⇒bk1=dk2
由于
n
≤
1
0
9
n\leq 10^9
n≤109,因为
2
32
>
1
0
9
2^{32}>10^9
232>109,于是
i
≤
32
i\leq 32
i≤32,所以考虑枚举
k
1
,
k
2
k_{1},k_{2}
k1,k2,由于
a
≠
c
a\neq c
a=c,即
k
1
≠
k
2
k_{1}\neq k_{2}
k1=k2,此时方程解的组数就是方案数,先化简方程至
g
c
d
(
k
1
,
k
2
)
=
1
gcd(k_{1},k_{2})=1
gcd(k1,k2)=1,即解
b
d
=
k
2
k
1
\frac{b}{d}=\frac{k_{2}}{k_{1}}
db=k1k2
设
b
=
k
2
x
≤
n
,
d
=
k
1
x
≤
n
b=k_{2}x\leq n,d=k_{1}x \leq n
b=k2x≤n,d=k1x≤n,有
x
≤
m
i
n
{
n
k
1
,
n
k
2
}
x\leq min\{\frac{n}{k_{1}},\frac{n}{k_{2}}\}
x≤min{k1n,k2n},
如果不化简,这个 x x x可能不是最大的
最后,这个序列的元素的都用最小的 x x x统计了,所以 x x x的其他幂需要跳过,数组记录即可
// #include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
using ll=long long;
const int N=1e5+5,inf=0x3fffffff;
const long long INF=0x3fffffffffffffff,mod=1e9+7;
ll n,ans;
bool vis[N];
int main()
{
cin>>n; ans=(1ll*n*n%mod+1ll*n*(n-1)%mod)%mod;
int limit=sqrt(n);
for(int i=2;i<=limit;i++)
{
if(vis[i]) continue;
ll max1=1,now=i;
while(now*i<=n) max1++,now*=i;
now=i;
for(int j=1;j<=max1;j++)
{
if(now<=limit) vis[now]=true;
for(int k=1;k<=max1;k++)
if(j!=k) ans=(ans+n/max(j/__gcd(j,k),k/__gcd(j,k)))%mod;
now*=i;
}
}
cout<<ans;
return 0;
}