【BZOJ 2818】Gcd - 筛法求素数&phi()
2016-03-12 13:28
411 查看
题目描述
给定整数NN,求1≤x,y≤N1\leq x,y\leq N且gcd(x,y)\gcd(x,y)为素数的数对(x,y)(x,y)有多少对.1≤N≤1071\leq N\leq 10^7
分析
首先筛出所有的素数。我们考虑枚举素数p,统计满足gcd(x,y)=p\gcd(x,y)=p的个数,等价于统计gcd(xp,yp)=1\gcd({x\over p},{y\over p})=1的个数,即统计[1,Np][1,{N\over p}]以内满足互质的有序数对个数dN/pd_{N/p}。
不难发现d1=1,di=di−1+2∗ϕ(i)d_1=1,d_i=d_{i-1}+2*\phi(i),也就是说,我们只要预处理出欧拉函数ϕ\phi,就可以在O(n)O(n)之内求出dd。
我们只需要用线性筛预处理出素数和欧拉函数,然后求dd,就可以在O(n)O(n)内解决问题。
代码
#include <cstdio> typedef long long lint; const int N=10000010; int n; int vis ; int pri ; int phi ; lint d ; lint res; int main(void) { scanf("%d",&n); vis[0]=vis[1]=1,phi[1]=1; for (int i=2;i<=n;i++) { if (!vis[i]) pri[++pri[0]]=i,phi[i]=i-1; for (int j=1;j<=pri[0];j++) { if ((lint)i*pri[j]>n) break; vis[i*pri[j]]=1; if (i%pri[j]) phi[i*pri[j]]=phi[i]*phi[pri[j]]; else phi[i*pri[j]]=phi[i]*pri[j]; if (i%pri[j]==0) break; } } d[1]=1; for (int i=2;i<=n;i++) d[i]=d[i-1]+phi[i]*2; for (int i=1;i<=pri[0];i++) res=res+d[n/pri[i]]; printf("%lld\n",res); return 0; }
相关文章推荐
- Goldengate 使用definition file完成异构表同步
- event 事件 冒泡
- 再思linux内核在中断路径内不能睡眠/调度的原因(2010)
- POI 实现甘蔗图报表与效果图
- 【2016.3.12】chown 解析
- 缩放夹逼求极限_20160312
- IOS8与IOS9不同点
- SublimeTest配置笔记
- shell中for循环总结
- C++实验1-三个整数输出最大值
- Andrew NG机器学习课程笔记系列之——Introduction to Machine Learning
- Andrew NG机器学习课程笔记系列之——从导数谈起
- 2016年3月11日Android学习日记
- jsp 页面和 jsp标记
- mongoose中如何给数据添加对应schema中没有的字段
- java内存溢出
- HDU 1010 Tempter of the Bone (搜索 + 奇偶剪枝)
- egnaRsrebmuNfoDNAesiwtiB.201
- js将echarts图表转换成base64位格式编码的图片
- 对我们最常用的软件QQ的看法