BZ OJ 2818 Gcd (欧拉函数)


交给我的任务是 莫比乌斯反演,从欧拉函数看起,好吧,  这道题 只是 应用到了 欧拉函数


2818: Gcd

Time Limit: 10 Sec  Memory Limit: 256 MB
Submit: 5827  Solved: 2596
[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


123

求 GCD(x,y)= 素数,   x,y 小于n  枚举小于n的素数,  (提前打表,)  

由欧拉函数  知道φ(x)=    而每一个素数对其的贡献为 (1-n/p)中有序互质对的个数,

 当y>=x时 只有x=y =1 时 互质, 

ans= 个数*2 -1   因为 (1,1) 多算了一次;


#include <iostream>
#include <algorithm>
#include <queue>
#include <stdio.h>
#include <cmath>
#include <cstring>

typedef long long ll;

using namespace std;
const int N =10000010;

bool vis[N];
ll p[N];
ll phi[N];
ll sum[N];
int cont;
int n;
void get_phi(int n)// p是素数
{
    cont=0;
	memset(vis,0,sizeof(vis));
    for(int i=2; i<=n; i++)
	{
        if(!vis[i])
		{
            p[++cont]=i;
            phi[i] = i-1;
        }
        for(int j=1; j<=cont && p[j]*i<=n; j++)
		{
            vis[p[j]*i]=1;
            if(i%p[j]==0)
			{
                phi[i*p[j]] = p[j] * phi[i]; //欧拉函数性质
                break;
            }
			else phi[i*p[j]] = (p[j]-1) * phi[i];
        }
    }
}

int main()
{
    int n;
    while(~scanf("%d",&n))
    {
        get_phi(n);
        ll res=0;
        sum[0]=1;
        for(int i=1;i<=n;i++)
            sum[i]=sum[i-1]+phi[i];
        for(int i=1;i<=cont;i++)
            res+=sum[n/p[i]]*2-1;

        printf("%lld\n",res);
    }
    return 0;
}


posted @ 2017-08-14 16:23  Sizaif  阅读(153)  评论(0编辑  收藏  举报