POJ-2773 Happy 2006(容斥版)
题意:给出,m和k,求第k个与m互质的数。m (1 <= m <= 1000000), K (1 <= K <= 100000000).
思路:容斥+二分,很巧妙的方法。
题目链接:http://poj.org/problem?id=2773
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <iostream> 2 #include <cstdio> 3 #include <cstdlib> 4 #include <cmath> 5 #include <cstring> 6 #include <string> 7 #include <algorithm> 8 #include <vector> 9 using namespace std; 10 #define LL long long 11 12 LL m,k; 13 vector<LL>v; 14 15 LL solve(LL x,LL n){ 16 v.clear(); 17 for(int i=2;i*i<=x;i++) 18 if(x%i==0){ 19 v.push_back(i); 20 while(x%i==0) x/=i; 21 } 22 if(x>1) v.push_back(x); 23 LL sum=0; 24 for(LL i=1;i<1<<v.size();i++){ 25 LL val=1,cnt=0; 26 for(LL j=0;j<v.size();j++){ 27 if(i&1<<j){ 28 val*=v[j]; 29 cnt++; 30 } 31 } 32 if(cnt&1) sum+=n/val; 33 else sum-=n/val; 34 } 35 return n-sum; 36 } 37 38 int main(){ 39 40 // freopen("data.in","r",stdin); 41 // freopen("data.out","w",stdout); 42 43 while(scanf("%lld%lld",&m,&k)!=EOF){ 44 LL l=1,r=1LL<<62; 45 LL ans; 46 while(l<=r){ 47 LL mid=(l+r)>>1; 48 LL num=solve(m,mid); 49 if(num>=k){ 50 r=mid-1; 51 if(num==k) ans=mid; 52 } 53 else l=mid+1; 54 } 55 printf("%lld\n",ans); 56 } 57 return 0; 58 }