bzoj 2818: Gcd

2818:GCD

Time Limit: 10 Sec Memory Limit: 256 MB
Submit: 6967 Solved: 3085
[submit] [status] [discuss]
Description

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

Input

一个整数N

Output

如题

Sample Input

4

Sample Output

4

HINT

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

1<=N<=10^7

想说的话

我的数论一直很菜 看了看题解发现是莫比乌斯反演但是我不会
于是乎我就自己想啊想
想到了欧拉函数

题解

我们先用一个函数算出phi函数的值
然后我们思考一下这个题我们就相当于从gcd(a,b)为素数
变成了对于每个范围里面的素数【1,b/a】中有序互质数对的个数
而求1~m中有序互质对x,y的个数,可以令y >= x, 当y = x时,有且只有y = x = 1互质,当y > x时,确定y以后符合条件的个数x就是phiy
所以有序互质对的个数为(1 ~ n/p)的欧拉函数之和乘2减1(要求的是有序互质对,乘2以后减去(1, 1)多算的一次)
那么就只需要先筛出欧拉函数再求个前缀和就可以了

代码

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
using namespace std;
#define N 10000005
#define ll long long
ll sum[N],phi[N],pri[1000001],n,p,tot,ans;
bool mark[N];
void getphi()
{
    phi[1]=1;
    for(ll i=2;i<=n;i++)
    {
        if(!mark[i]){phi[i]=i-1;pri[++tot]=i;}
        for(ll j=1;j<=tot;j++)
        {
            ll x=pri[j];
            if(i*x>n)break;
            mark[i*x]=1;
            if(i%x==0){phi[i*x]=phi[i]*x;break;}
            else phi[i*x]=phi[i]*phi[x];
        }
    }
}
int main()
{
    scanf("%lld",&n);
    getphi();
    for(int i=1;i<=n;i++)
    {
        sum[i]=sum[i-1]+phi[i];
    }
    for(int i=1;i<=tot;i++)
    {
        ans+=sum[n/pri
[i]]*2-1;
    }
    cout<<ans<<endl;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值