Bzoj 2818: Gcd 莫比乌斯,分块,欧拉函数,线性筛

2818: Gcd

Time Limit: 10 Sec  Memory Limit: 256 MB
Submit: 3241  Solved: 1437
[Submit][Status][Discuss]

Description

给定整数N,求1<=x,y<=N且Gcd(x,y)为素数的
数对(x,y)有多少对.

 

Input

一个整数N

Output

如题

Sample Input

4

Sample Output

4

HINT

 

hint

对于样例(2,2),(2,4),(3,3),(4,2)


1<=N<=10^7

 

Source

湖北省队互测

题解:

莫比乌斯函数或欧拉函数。

莫比乌斯函数详见 Popoqqq的课件 (Orz Po姐)

之后就自己推公式吧。。。

莫比乌斯函数:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define LL long long
 4 #define MAXN 10000010
 5 int prime[670010],mu[MAXN],qz[MAXN],tot,N;
 6 bitset<MAXN> vis;
 7 int read()
 8 {
 9     int s=0,fh=1;char ch=getchar();
10     while(ch<'0'||ch>'9'){if(ch=='-')fh=-1;ch=getchar();}
11     while(ch>='0'&&ch<='9'){s=s*10+(ch-'0');ch=getchar();}
12     return s*fh;
13 }
14 void getmu()
15 {
16     int i,j;
17     mu[1]=1;
18     tot=0;
19     for(i=2;i<=N;i++)
20     {
21         if(vis[i]==0)
22         {
23             prime[++tot]=i;
24             mu[i]=-1;
25         }
26         for(j=1;j<=tot&&prime[j]*i<=N;j++)
27         {
28             vis[prime[j]*i]=1;
29             if(i%prime[j]==0)
30             {
31                 mu[i*prime[j]]=0;
32                 break;
33             }
34             mu[i*prime[j]]=-mu[i];
35         }
36     }
37 }
38 void Qz()
39 {
40     for(int i=1;i<=N;i++)qz[i]=qz[i-1]+mu[i];
41 }
42 LL calc(int n)
43 {
44     int d,pos;
45     LL sum=0;
46     for(d=1;d<=n;d=pos+1)
47     {
48         pos=n/(n/d);
49         sum+=(LL)(n/d)*(n/d)*(qz[pos]-qz[d-1]);
50     }
51     return sum;
52 }
53 int main()
54 {
55     int i;
56     LL ans=0;
57     N=read();
58     getmu();
59     Qz();
60     for(i=1;i<=tot&&prime[i]<=N;i++)ans+=calc(N/prime[i]);
61     printf("%lld",ans);
62     fclose(stdin);
63     fclose(stdout);
64     return 0;
65 }
View Code

 欧拉函数:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define MAXN 10000010
 4 #define LL long long
 5 bitset<MAXN> vis;
 6 int N,prime[670010],phi[MAXN],tot;
 7 LL qz[MAXN];
 8 int read()
 9 {
10     int s=0,fh=1;char ch=getchar();
11     while(ch<'0'||ch>'9'){if(ch=='-')fh=-1;ch=getchar();}
12     while(ch>='0'&&ch<='9'){s=s*10+(ch-'0');ch=getchar();}
13     return s*fh;
14 }
15 void geteular()
16 {
17     int i,j;
18     phi[1]=1;tot=0;
19     for(i=2;i<=N;i++)
20     {
21         if(vis[i]==0)
22         {
23             prime[++tot]=i;
24             phi[i]=i-1;
25         }
26         for(j=1;j<=tot&&prime[j]*i<=N;j++)
27         {
28             vis[prime[j]*i]=1;
29             if(i%prime[j]==0)
30             {
31                 phi[prime[j]*i]=phi[i]*prime[j];
32                 break;
33             }
34             phi[prime[j]*i]=phi[prime[j]]*phi[i];
35         }
36     }
37 }
38 void Qz()
39 {
40     qz[0]=qz[1]=0;
41     for(int i=2;i<=N;i++)qz[i]=qz[i-1]+phi[i];
42 }
43 int main()
44 {
45     int i,n;
46     LL ans=0;
47     N=read();
48     geteular();
49     Qz();
50     for(i=1;i<=tot;i++)
51     {
52         n=N/prime[i];
53         ans+=(qz[n]*2+1);
54     }
55     printf("%lld",ans);
56     fclose(stdin);
57     fclose(stdout);
58     return 0;
59 }
View Code

 

posted @ 2016-03-16 18:06  微弱的世界  阅读(175)  评论(0编辑  收藏  举报