hdu 3388二分 容斥原理

复习容斥原理(其实当时就没学会,看到的题,拿出来再研究一下方便日后复习,

题意:给三个数m,n,k, 0<m,n,k<10^9,求与m,n同时互质的第k个正整数(按从小到达顺序排列).

 
这里本质的问题就是容斥原理的最基础的应用,求1-n中与x互质的数有多少,如果知道这个的解法,那么不就是n*m就是x,二分n就可以了,
这里n*m肯定不行,所以分开分解unique一下就行了。。
 
#include <iostream>
#include <cstring>
#include <vector>
#include <cmath>
#include <algorithm>
using namespace std;

long gcd(long long a,long long b){
    return b==0?a:gcd(b,a%b);
}

vector<long long> v;
int num=0;

void prime(long long n){
    for(long long i=2;i*i<=n;i++){
        if(n%i==0){
            v.push_back(i);
            while(n%i==0){
                n=n/i;
            }
        }
    }
    if(n>1)
        v.push_back(n);
    return;
}

long long dfs(int idx,long long n){
    long long ret=0;
    for(int i=idx;i<num;i++){
        ret+=n/v[i]-dfs(i+1,n/v[i]);
    }
    return ret;
}

void solve(long long s,long long t,long long k){
    long long l=s,r=t;
    while(l<=r){
        long long mid=(l+r)/2;
        if(mid-dfs(0,mid)<k) l=mid+1;
        else r=mid-1;
    }
    cout<<l<<endl;
    return;
}

int main()
{
    long long t;
    long long a,b,k;
    long long cas=1;
    cin>>t;
    while(t--){
        cin>>a>>b>>k;
        long long g=a*b/gcd(a,b);
        v.clear();
        prime(a);
        prime(b);
        sort(v.begin(),v.end());
        num=unique(v.begin(),v.end())-v.begin();
        cout<<"Case "<<cas++<<": ";
        long long t=1e18+5;
        solve(1,t,k);
    }
}


原文地址:https://www.cnblogs.com/zhangxianlong/p/10672582.html