POJ 2773 Happy 2006 题解与分析
2013-08-17 19:58
495 查看
[align=center]Happy 2006[/align]
Description
两个正整数如果称为互质,那么应满足这两数的最大公约数(GCD)为1。例如,1,3,5,7,9……都与2006互质。你现在的工作很容易:对于给定的整数m,找到第k个与M互质的元素,这些元素是以升序排序。
Input
输入包含多个测试案例。对于每个测试案例,它包含两个整数m(1 <= m <= 1000000), K (1 <= K <= 100000000).
Output
对于每个案例,输出第k大的与M互质的数,每个数占一行
Sample Input
Sample Output
Source
POJ Monthly--2006.03.26
Translation
初学者 http://blog.csdn.net/csyzcyj
【分析】:
这道题目首先想到二分一个数x,表示所求答案在区间[1,x]内,现在需要验证是否在区间[1,x]内有且仅有k个与M互质的数,即求[1,x]中与M互质的数的个数z。这里求z值需转换思想,因为求M的约数比求与M互质的数更快,而求约数可以用M分解因数后的值配上容斥原理解决。那么首先将M分解因数p1-pn,存在数组mult中。
因为x在区间[1,y]中的倍数有y/x<向下取整>个,那么根据容斥原理,在区间[1,x]内是M的倍数的数为:
即所有数集合-M以内所有一个素因子构成的因子的个数+M以内所有两个素因子构成的因子的个数-M以内所有三个素因子构成的因子的个数...,那么与M互质的个数就为X-区间[1,x]内是M的倍数的数。
注意:二分验证完后,不应急于结束二分,因为这里是要求一个下限值x,即在区间[1-x)中与M互质的数的数量刚好小于K,因此应继续让他二分下去
【代码】:
转载注明出处:http://blog.csdn.net/u011400953
Time Limit: 3000MS | Memory Limit: 65536K | |
Total Submissions: 8447 | Accepted: 2777 |
两个正整数如果称为互质,那么应满足这两数的最大公约数(GCD)为1。例如,1,3,5,7,9……都与2006互质。你现在的工作很容易:对于给定的整数m,找到第k个与M互质的元素,这些元素是以升序排序。
Input
输入包含多个测试案例。对于每个测试案例,它包含两个整数m(1 <= m <= 1000000), K (1 <= K <= 100000000).
Output
对于每个案例,输出第k大的与M互质的数,每个数占一行
Sample Input
2006 1 2006 2 2006 3
Sample Output
1 3 5
Source
POJ Monthly--2006.03.26
Translation
初学者 http://blog.csdn.net/csyzcyj
【分析】:
这道题目首先想到二分一个数x,表示所求答案在区间[1,x]内,现在需要验证是否在区间[1,x]内有且仅有k个与M互质的数,即求[1,x]中与M互质的数的个数z。这里求z值需转换思想,因为求M的约数比求与M互质的数更快,而求约数可以用M分解因数后的值配上容斥原理解决。那么首先将M分解因数p1-pn,存在数组mult中。
因为x在区间[1,y]中的倍数有y/x<向下取整>个,那么根据容斥原理,在区间[1,x]内是M的倍数的数为:
即所有数集合-M以内所有一个素因子构成的因子的个数+M以内所有两个素因子构成的因子的个数-M以内所有三个素因子构成的因子的个数...,那么与M互质的个数就为X-区间[1,x]内是M的倍数的数。
注意:二分验证完后,不应急于结束二分,因为这里是要求一个下限值x,即在区间[1-x)中与M互质的数的数量刚好小于K,因此应继续让他二分下去
【代码】:
/* Memory: 8000K Time: 63MS Language: C++ Result: Accepted */ #include<stdio.h> #include<string.h> #include<stdlib.h> #include<algorithm> #include<iostream> #include<vector> #include<stack> #include<queue> using namespace std; #define MAX 1000001 #define IMAX 2147483647 long long M,K,ans,tot=0,change=1; long long mult[MAX],use[MAX]; void divide1(long long x) { memset(mult,0,sizeof(mult)); for(long long i=2;i*i<=x;i++) if(x%i==0) { mult[++tot]=i; while(x%i==0) x/=i; } if(x>1) mult[++tot]=x; } long long check(long long x) { long long sum=0; for(long long num=1;num<(1<<tot);num++)//二进制枚举的容斥 { long long nowsum=1,cnt=0; for(int i=1;i<=tot;i++) { if(num&(1<<(i-1))) { cnt++; nowsum*=mult[i]; } } if(cnt%2) sum+=x/nowsum; else sum-=x/nowsum; } return (x-sum); } int main() { //freopen("input.in","r",stdin); //freopen("output.out","w",stdout); while(scanf("%lld%lld",&M,&K)!=EOF) { tot=0; divide1(M); long long left=1,right=IMAX; while(left<=right) { long long middle=(left+right)/2; long long now=check(middle); if(now>=K) { right=middle-1; if(now==K) ans=middle; } else left=middle+1; } printf("%lld\n",ans); } //system("pause"); return 0; }
转载注明出处:http://blog.csdn.net/u011400953
相关文章推荐
- Happy 2006 POJ - 2773 数论
- POJ 2773 Happy 2006
- poj 2773 Happy 2006
- POJ - 2773 Happy 2006 (互素的一点性质)
- POJ 2773 Happy 2006
- POJ 2773 Happy 2006
- POJ 2773 Happy 2006
- POJ 2773 Happy 2006 (容斥原理)
- (Relax 1.15)POJ 2773 Happy 2006(欧拉函数的应用:求与n互质的第k个数)
- POJ 2773 Happy 2006 (容斥原理+二分)
- POJ 2773-Happy 2006(欧拉函数)
- poj 2773 Happy 2006
- poj 2773 Happy 2006——欧拉函数
- POJ_2773_Happy 2006_ 欧几里得算法
- poj 2773 Happy 2006
- POJ 2773:Happy 2006 - 第k大与n互素的数
- POJ_2773_happy_2006(欧拉公式)
- poj2773 Happy 2006(二分+容斥)
- Poj 2773 Happy 2006(枚举互素数)
- poj 2773 Happy 2006