GCD
题目描述
给定正整数 n n n,求 1 ≤ x , y ≤ n 1\le x,y\le n 1≤x,y≤n 且 gcd ( x , y ) \gcd(x,y) gcd(x,y) 为素数的数对 ( x , y ) (x,y) (x,y) 有多少对。
输入格式
只有一行一个整数,代表 n n n。
输出格式
一行一个整数表示答案。
样例 #1
样例输入 #1
4
样例输出 #1
4
提示说明
样例输入输出 1 解释
对于样例,满足条件的 ( x , y ) (x,y) (x,y) 为 ( 2 , 2 ) (2,2) (2,2), ( 2 , 4 ) (2,4) (2,4), ( 3 , 3 ) (3,3) (3,3), ( 4 , 2 ) (4,2) (4,2)。
数据规模与约定
- 对于 100 % 100\% 100% 的数据,保证 1 ≤ n ≤ 1 0 7 1\le n\le10^7 1≤n≤107。
来源:bzoj2818。
本题数据为洛谷自造数据,使用 CYaRon 耗时 5 5 5 分钟完成数据制作。
// #include <iostream>
// #include <algorithm>
// #include <cstring>
// #include <stack>//栈
// #include <deque>//队列
// #include <queue>//堆/优先队列
// #include <map>//映射
// #include <unordered_map>//哈希表
// #include <vector>//容器,存数组的数,表数组的长度
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll N=1e7+10;
ll p[N],cnt;
ll phi[N],num[N];
bool st[N];
//筛法求欧拉函数(线性筛法)
void eulers(ll n)
{
phi[1]=1;
for(ll i=2;i<=n;i++)
{
if(!st[i])
{
p[++cnt]=i;
// i 为质数,即欧拉值为 i-1
phi[i]=i-1;
}
for(ll j=1;p[j]<=n/i;j++)
{
ll t=p[j]*i;
st[t]=1;
if(i%p[j]==0)
{
phi[t]=phi[i]*p[j];
break;
}
phi[t]=phi[i]*(p[j]-1);
}
}
for(ll i=1;i<=n;i++)//前缀和
num[i]=num[i-1]+phi[i];
}
int main()
{
ll n;
cin>>n;
//筛法求欧拉函数(线性筛法)
eulers(n);
ll res=0;//数对数目
for(ll i=1;i<=cnt;i++)
res+=2*num[n/p[i]]-1;
cout<<res<<endl;
return 0;
}