bzoj 2818 Gcd 线性筛欧拉+想法

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

扫描二维码关注公众号,回复: 2864683 查看本文章

思路:假如n为11,求11以前的质数,以其中的一个 2为例

在[1,11]中,以gcd(x,y)==2 是2,4,6,8,10,的组合,若gcd(x,y)/2 ==1,等同于求(2/2,4/2,6/2,8/2,10/2)==(1,2,3,4,5)中到

5的一定互质的个数,即求phi[1-5]的值,因为x,y的限制仅为[1,n],个数为2*phi[1-5]-1,(2,2)只有一个会重复计算。

#include<map>
#include<set>
#include<queue>
#include<stack>
#include<cmath>
#include<deque>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;

typedef long long ll;
const int inf = 0x3f3f3f3f;
const int M = 1e7 + 10;
ll n;
ll prime[M],phi[M];
bool vis[M];
void eular()
{
    ll cnt=0;
    memset(vis,true,sizeof(vis));
    phi[1]=1;
    for(ll i=2;i<M;i++)
    {
        if(vis[i])
        {
            prime[cnt++]=i;
            phi[i]=i-1;
        }
        for(ll j=0;j<cnt && i*prime[j]<M;j++)
        {
            ll k=i*prime[j];
            vis[k]=false;
            if(i%prime[j]==0)
            {
                phi[k]=phi[i]*prime[j];
                break;
            }
            else
                phi[k]=phi[i]*(prime[j]-1);
        }
    }
    for(int i=1;i<M;i++){
        phi[i]+=phi[i-1];
        //cout<<i<<" "<<phi[i]<<endl;
    }
}
int main()
{
    eular();
    while(~scanf("%lld",&n))
    {
        ll ans=0;
        for(ll i=2;i<=n;i++)
        {
            if(vis[i])
            {
                //cout<<phi[n/i]<<endl;
                ans+=phi[n/i]*2-1;
            }
        }
        printf("%lld\n",ans);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/liluoyu_1016/article/details/81810785