poj 2773 容斥原理+二分

来源:互联网 发布:天书机甲进阶数据 编辑:程序博客网 时间:2024/05/01 22:07


 Two positive integers are said to be relatively prime to each other if the Great Common Divisor (GCD) is 1. For instance, 1, 3, 5, 7, 9...are all relatively prime to 2006.

Now your job is easy: for the given integer m, find the K-th element which is relatively prime to m when these elements are sorted in ascending order.
Input
The input contains multiple test cases. For each test case, it contains two integers m (1 <= m <= 1000000), K (1 <= K <= 100000000).
Output
Output the K-th element in a single line.
Sample Input
2006 12006 22006 3
Sample Output
135

二分区间[1,inf],对于某个mid=x,利用容斥原理求[1,x]中与m不互质的数的个数num,不互质的个数x-num与k比较,二分找到最小的x值

#include<iostream>#include<cmath>#include<cstring>#define inf 0x3f3f3f3f#define ll long longusing namespace std;int fac[1000010];ll sum;void eular(int n){    int m=sqrt(n+0.5);    int x=1;    for(int i=2;i<=m;i++)        if(n%i==0)        {            fac[x++]=i;            while(n%i==0)                n=n/i;        }    if(n>1)        fac[x++]=n;    fac[0]=x-1;}ll gcd(ll a,ll b){    return b==0?a:gcd(b,a%b);}ll lcm(ll a,ll b){    return a/gcd(a,b)*b;}void dfs(int id,int cur,ll lcmx,ll x){    int lcmxx=lcm(lcmx,fac[id]);    if(cur%2==1)        sum+=x/lcmxx;    else        sum-=x/lcmxx;    for(int i=id+1;i<=fac[0];i++)        dfs(i,cur+1,lcmxx,x);}ll solve(ll x){    sum=0;    for(int i=1;i<=fac[0];i++)        dfs(i,1,fac[i],x);    return x-sum;}int main(){    int n,k;    while(cin>>n>>k)    {        eular(n);        ll l=1,r=inf;        while(l<r)        {            ll mid=(l+r)>>1;            if(solve(mid)>=k)                r=mid;            else                l=mid+1;        }        cout<<l<<endl;    }    return 0;}


0 0
原创粉丝点击