POJ2773 二分+容斥原理 xingxing在努力

这一个题就是求解第k个和n互质的数, 像这种求解第k个数的一般都可以用二分解决, 前提是可以求得一个区间内满足条件的数的个数, 对于这一道题假设我们知道1-n的区间中和n互质的个数, 那么我们就可以通过二分快速的定位这个数。。利用容斥原理求出1-n中不与n互质的数的个数, 用n减去这个数就是要求得数。。代码如下:

 

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <iostream>

using namespace std;
typedef long long LL;
int m, k;

int factor[50], cnt;

void getfactor(int n)
{
    cnt = 0;
    int m = sqrt(n+0.5);
    for(int i=2; i<=m; i++) if(n%i == 0)
    {
        factor[cnt++] = i;
        while(n%i==0) n/=i;
    }
    if(n > 1) factor[cnt++] = n;   //不要忘记呀,贡献了几发wa
}

LL getnum(LL n)   //获取1-n中和m互质的数的个数
{
    if(m == 1) return n;
    if(n == 1) return 1;
    LL res = n;
    for(int i=1; i<(1<<cnt); i++)
    {
        LL temp = i, a=0, b=1;
        for(int j=0; j<cnt; j++)
        {
            if((temp&1) == 1)
            {
                b *= factor[j];
                a++;
            }
            temp >>= 1;
        }
        if((a&1)==1) res -= n/b;
        else res += n/b;
    }
    return res;
}

int main()
{
    while(scanf("%d%d", &m, &k) == 2)
    {
        getfactor(m);
        LL low=1, high = (1LL<<62);
        LL ans;
        while(low <= high)
        {
            LL mid = (low+high)/2;
            LL num = getnum(mid);
            if(num > k) high = mid - 1;
            else if(num < k) low = mid + 1;
            else
            {
                ans = mid;
                high = mid - 1;
            }
        }
        cout<<ans<<endl;
    }
    return 0;
}

 

posted @ 2015-11-10 22:19  xing-xing  阅读(225)  评论(0)    收藏  举报