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){
    //v.clear();
    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 m=(s+t)/2;
    long long b=m-dfs(0,m);
   if(b==k){
        while(1){
            if(m>1&&m-1-dfs(0,m-1)==b)
                m--;
            else
                break;
        }
        cout<<m<<endl;
        return ;
    }
    if(b<k){
        solve(m+1,t,k);
    }
    else if(b>k){
        solve(s,m-1,k);
    }
    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);
    }
}


你可能感兴趣的:(hdu 3388二分 容斥原理)