博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[bzoj 2818]GCD
阅读量:6622 次
发布时间:2019-06-25

本文共 2202 字,大约阅读时间需要 7 分钟。

Gcd

Time Limit: 10 Sec  Memory Limit: 256 MB

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

题解:

根据题意,我们要求求1<=x,y<=N且Gcd(x,y)为素数的数对(x,y)有多少对。

显然我们不可能将1到N的所有数对都枚举一遍,现在考虑枚举所有质数。

因为gcd(a,b)==p(p为质数),所以gcd(a/p,b/p)==1;

那么我们只要枚举所有小于N的质数,然后找⌊a/p⌋和⌊b/p⌋互质的对数。

显然只要先预处理出欧拉函数,然后用一层循环枚举1~⌊a/p⌋统计一下和就可以了。

注意一下几点:

1.每次统计都要乘上2,因为反过来也算一个数对。比如样例中2,4和4,2是不同的数对。

2.每次统计完之后ans-- 因为每次统计都乘2必然会有一个包含两个相同数的数对被多计算一次,比如样例中2,2和3,3都被计算了两次,所以要被减掉。

3.至于怎么筛质数,欧拉函数,以及高端大气上档次的莫比乌斯函数,实际上可以同时做到。

 

void find_prime(int listsize){    int i,j;    memset(isprime,1,sizeof(isprime));    isprime[1]=false;    phi[1]=1;    mu[1]=1;    for(i=2;i<=listsize;i++)    {        if(isprime[i])        {            prime[++primesize]=i;            phi[i]=i-1;            mu[i]=-1;        }        for(j=1;j<=primesize&&i*prime[j]<=listsize;j++)        {            isprime[i*prime[j]]=false;            if(i%prime[j]==0)            {                phi[i*prime[j]]=phi[i]*prime[j];                mu[i*prime[j]]=0;                break;            }            else             {                phi[i*prime[j]]=phi[i]*(prime[j]-1);                mu[i*prime[j]]=-mu[i];            }        }    }    return;}

 

然后附上AC代码:

 

#include
#include
#include
#include
#include
#include
using namespace std;typedef long long lol;bool isprime[10000001];int prime[5000001],primesize,phi[10000001],n;lol ans;void find_prime(int listsize){ int i,j; memset(isprime,1,sizeof(isprime)); isprime[1]=false; phi[1]=1; for(i=2;i<=listsize;i++) { if(isprime[i]) { prime[++primesize]=i; phi[i]=i-1; } for(j=1;j<=primesize&&i*prime[j]<=listsize;j++) { isprime[i*prime[j]]=false; if(i%prime[j]==0) { phi[i*prime[j]]=phi[i]*prime[j]; break; } else { phi[i*prime[j]]=phi[i]*(prime[j]-1); } } } return;}int main(){ int i,j; scanf("%d",&n); find_prime(n); for(i=1;i<=primesize;i++) { int to=n/prime[i]; for(j=1;j<=to;j++) ans+=phi[j]*2; ans--; } printf("%lld\n",ans); return 0;}

 

 

 

 

 

转载于:https://www.cnblogs.com/huangdalaofighting/p/7275988.html

你可能感兴趣的文章
【BZOJ】3832: [Poi2014]Rally
查看>>
[转]看懂ExtJS的API
查看>>
宜昌民生大厦
查看>>
推荐15款制作 SVG 动画的 JavaScript 库
查看>>
陀螺仪原理--网上转载
查看>>
转:OpenResty最佳实践(推荐了解lua语法)
查看>>
转:CEO, CFO, CIO, CTO, CSO是什么
查看>>
P2P之UDP穿透NAT的原理与实现 - 增强篇(附修改过的源代码)
查看>>
添加 All Exceptions 断点后, 每次运行都会在 main.m 中断的一种解决方法
查看>>
[Ubuntu] fg、bg让你的进程在前后台之间切换
查看>>
二维数组与类的定义_DAY06
查看>>
ROC曲线(receiver-operating-characteristic curve)-阈值评价标准(转)
查看>>
Swift 表达式
查看>>
FFmpeg(8)-打开音视频解码器,配置解码器上下文(avcodec_find_decoder()、avcodec_alloc_context3())...
查看>>
Javascript基础恶补
查看>>
andriod自定义视图
查看>>
linux下vim更改注释颜色
查看>>
在SSL / https下托管SignalR
查看>>
Using JRuby with Maven
查看>>
poj 3308 (最大流)
查看>>