【河北省队互测】 gcd BZOJ 2818

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

思路

    最近看了很多关于gcd和mod的题目。

    通过最近几道题目了解了很多=。=

   首先有这么一个性质:如果a∈[1,n],b∈[1,m],那么gcd(a,b)|k的有(n/k)*(m/k)组。

   那么令f[x]为gcd(a,b)==k的组数,f[k]=(n/k)*(m/k)-f[2k]-f[3k]-f[4k]……

   对于这一题来说。。好像是并不可以过的。

   那么就有别的性质:

   如果a,b∈[1,n],gcd(a,b)==k的组数等价于a,b∈[1,n/k],gcd(a,b)==1的组数。

   这就很好求了吧,就是1->n的phi值之和(欧拉函数)*2-1。

   首先每组数必须要算两遍,比如(3,5)和(5,3),所以要*2。然后(1,1)不要算两遍,所以再-1。

   然后就是如何求出1-n中所有的质数以及欧拉函数了。现场学习线性筛。。

   其实我完全不理解啊。。先记住好了。。核心代码如下:

 1 phi[1]=1;memset(is_prime,true,sizeof(is_prime));
 2 for(int i=2;i<=n;i++){
 3     if (is_prime[i]){
 4        phi[i]=i-1;
 5        prime[++cnt]=i;      
 6     }    
 7     for(int j=1;j<=cnt&&i*prime[j]<=n;j++){
 8        is_prime[i*prime[j]]=false;
 9        if (i%prime[j]!=0)  phi[i*prime[j]]=phi[i]*(prime[j]-1);
10        else{
11          phi[i*prime[j]]=phi[i]*prime[j];
12          break;
13        }
14     }
15 }
线性筛

   应该没写错吧。。为了加强记忆默写的。。如果有问题就看下面的那个版本吧,那个是AC了的。

  

 1 #include <iostream>
 2 #include <cstring>
 3 #include <string>
 4 #include <cstdio>
 5 #include <cstdlib>
 6 #include <cmath>
 7 #include <algorithm>
 8 #include <queue>
 9 #include <stack>
10 #include <map>
11 #include <set>
12 #include <list>
13 #include <vector>
14 #include <ctime>
15 #include <functional>
16 #define pritnf printf
17 #define scafn scanf
18 #define sacnf scanf
19 #define For(i,j,k) for(int i=(j);i<=(k);(i)++)
20 #define Clear(a) memset(a,0,sizeof(a))
21 using namespace std;
22 typedef unsigned int Uint;
23 const int INF=0x3fffffff;
24 ///==============struct declaration==============
25 
26 ///==============var declaration=================
27 const int MAXN=10000050;
28 int n,tot=0,ans=0;
29 int prime[MAXN];
30 long long phi[MAXN];
31 bool is_prime[MAXN];
32 ///==============function declaration============
33 void Init();
34 ///==============main code=======================
35 int main()
36 {
37 //#define FILE__
38 #ifdef FILE__
39    freopen("input","r",stdin);
40    freopen("output","w",stdout);
41 #endif
42    scanf("%d",&n);
43    Init();
44    for(int i=1;i<=n;i++) phi[i]+=phi[i-1];
45    long long ans=0;
46    for(int i=1;i<=tot;i++)
47       ans+=phi[n/prime[i]]*2-1;
48    printf("%lld\n",ans);
49    return 0;
50 }
51 ///================fuction code====================
52 void Init(){
53    memset(is_prime,true,sizeof(is_prime));phi[1]=1;
54    for(int i=2;i<=n;i++){
55       if (is_prime[i]){
56          phi[i]=i-1;
57          prime[++tot]=i;
58       }
59       for(int j=1;j<=tot;j++){
60          if (i*prime[j]>n)   break;
61          is_prime[i*prime[j]]=false;
62          if (i%prime[j]==0){
63             phi[i*prime[j]]=phi[i]*prime[j];
64             break;
65          }
66          else
67             phi[i*prime[j]]=phi[i]*(prime[j]-1);
68       }
69    }
70 }
BZOJ2818

   不要问我那些性质是为什么。。我也布吉岛(╯‵□′)╯︵┻━┻

posted @ 2015-03-10 17:39  Houjikan  阅读(295)  评论(0编辑  收藏  举报