看到这是一道紫题还是和gcd有关的才点进来(毕竟数论只会gcd).
很明显,直接暴力需要O(N^2)的时间发咋读但是N有1e7肯定是会T的,所以需要从gcd(a,b)为一个质数入手.
当
g
c
d
(
a
,
b
)
=
=
1
gcd(a,b)==1
gcd(a,b)==1时不难发现
g
c
d
(
a
∗
p
,
b
∗
p
)
=
=
p
gcd(a*p,b*p)==p
gcd(a∗p,b∗p)==p(p为任何自然数时都成立),于是乎可以先把0~N中的素数筛出来.
那么下面要怎么知道一个素数可以产生几对符合条件的a,b呢?
可以发现
m
a
x
(
a
,
b
)
∗
p
≤
N
⇒
m
a
x
(
a
,
b
)
≤
N
p
max(a,b)*p\leq N\Rightarrow max(a,b)\leq \dfrac {N}{p}
max(a,b)∗p≤N⇒max(a,b)≤pN因为a,b都为整数,所以
m
a
x
(
a
,
b
)
≤
⌊
N
p
⌋
max(a,b)\leq \lfloor\dfrac {N}{p}\rfloor
max(a,b)≤⌊pN⌋,于是就要知道小于p的互质的数对的个数了,拿出前置芝士中的欧拉函数,于是小于p的数的对数
=
2
∗
∑
i
=
1
⌊
N
p
⌋
φ
(
i
)
=2*\sum ^{\tiny\lfloor\dfrac {N}{p}\rfloor}_{i=1}\varphi \left( i\right)
=2∗∑i=1⌊pN⌋φ(i)(因为如(1,2)和(2,1)同时成立,所以需要乘2),每次都要求自然还是会T,所以需要用到前缀和优化一下.
-
具体实现
- 欧拉函数的具体实现:(本人太菜,只会用埃氏筛)
对于x不是质数 φ ( x ) = x ∗ ∏ i = 1 n ( 1 − 1 p i ) \varphi(x)=x*\prod ^{n}_{i=1}(1-\dfrac {1}{p_{i}}) φ(x)=x∗∏i=1n(1−pi1)(其中 p i p_{i} pi为为x质因数,n为x的质因数的个数)
x为质数时 φ ( x ) = x − 1 \varphi(x)=x-1 φ(x)=x−1
其中十分特殊的 φ ( 1 ) = 1 \varphi(1)=1 φ(1)=1
这样可以直接套入埃氏筛中将所有 1 ≤ x ≤ N 1\leq x\leq N 1≤x≤N的 φ ( x ) \varphi(x) φ(x)求出,再用一个sum数组统计起来.
如果还不是很了解可以康康例题.
- 欧拉函数的具体实现:(本人太菜,只会用埃氏筛)
-
代码
#include<bits/stdc++.h>
#define rap(i,first,last) for(int i=first;i<=last;++i)
using namespace std;
const int maxN=1e7+5;
int N;
double phi[maxN];
bool boo[maxN];
long long sum[maxN];//注意开long long
int main()
{
scanf("%d",&N);
rap(i,1,N)
{
boo[i]=1;
phi[i]=i;//先赋值为i方便处理
}
boo[1]=0;//不是质数
rap(i,2,N)//埃氏筛的部分
if(boo[i])
{
phi[i]=i-1;
rap(j,2,N/i)
{
boo[i*j]=0;
phi[i*j]*=1.0-1.0/i;//求出欧拉函数的值
}
}
sum[1]=1;//1时因为只有(1,1)所以不用乘二
rap(i,2,N)
sum[i]=sum[i-1]+1ll*((int)phi[i])*2;//用前缀和优化
long long answer=0;//注意long long
rap(i,2,N)
if(boo[i])answer+=sum[N/i];//把每个质数所带来的(a,b)全部相加
printf("%lld",answer);//输出answer
return 0;
}
数论题的题解好难写