1 /**
2 大意: 给定整数N,1<= x,y <= N 求解有多少gcd(x,y) 为素数 n=10^7
3 思路: 首先考虑到n 如此之大,用的快速求欧拉函数。
4 先默认 y〉x
5 分析: gcd(x,y) =2, gcd(x,y) = 3, gcd(x,y) = 5, gcd(x,y) = 7。。。。
6 即 gcd(x,y/2) =1, gcd(x, y/3) =1, gcd(x, y/5) =1, gcd(x,y/7) = 1 。。。。
7 以gcd(x,y) = 2 为例 -----> gcd(x,y/2) = 1;
8 就是求比y/2小的所有与y/2 互质数的个数。。。y取值为2,4,6,8,10.。。。
9 所以siga(gcd(x,2)=2 + gcd(x,4) =2 + gcd( x,6) =2 + 。。。)=
10 ----->siga(gcd(x,1)=1 + gcd(x,2) =1 + gcd( x,3) =1 + 。+ gcd(x,n/2)=1)
11 其他的同理。。。
12 所以先预处理 小于n 的所有互质数的个数 s[i] = s[i-1]+phi[i];
13 使用时
14 if(n>=prime[i]){
15 ans += 2*s[n/prime[i]]-1; (也有可能x 〉y)
16 }
17 **/
18
19 #include <iostream>
20 #include <cstring>
21 #include <algorithm>
22 using namespace std;
23
24 #define Max 10000000
25
26 long long s[Max+5],f[Max+5],phi[Max+5];
27 int prime[Max/10];
28 bool flag[Max+5];
29 int num;
30 void init()
31 {
32 int i,j;
33 num=0;
34 memset(flag,1,sizeof(flag));
35 phi[1]=1;
36 for(i=2;i<=Max;i++){//欧拉筛选
37 if(flag[i])
38 {
39 prime[num++]=i;
40 phi[i]=i-1;
41 }
42 for(j=0;j<num && prime[j]*i<=Max;j++)
43 {
44 flag[i*prime[j]]=false;
45 if(i%prime[j]==0)
46 {
47 phi[i*prime[j]]=phi[i]*prime[j];
48 break;
49 }
50 else phi[i*prime[j]]=phi[i]*(prime[j]-1);
51 }
52 }
53 s[0] =0;
54 for(int i=1;i<Max;i++)
55 s[i] = s[i-1]+phi[i];
56 }
57
58
59 int main(){
60 init();
61 long long n;
62 while(cin>>n){
63 long long ans =0;
64 for(int i=0;i<num;i++)
65 if(n>=prime[i]){
66 ans += 2*s[n/prime[i]]-1;
67 }
68 cout<<ans<<endl;
69 }
70 }