POJ 2773 二分+容斥定理

来源:互联网 发布:调到数据网接入设备 编辑:程序博客网 时间:2024/05/22 14:22

不愧是我们的袁神,三分钟搞定...

题意不介绍了..

/*2773 Accepted 168K 0MS C++ 1030B 2012-12-14 21:12:23*/
#include <cstdio>

// 对n进行素因子分解, fac[0]记录因子个数;
int fac[10];
void Div(int n){
    int k= 0;
    for(int i=2; i*i<=n; ++i){
        if( n%i==0 ) fac[++k]= i;
        while(n%i==0) n/= i;
    }
    if( n>1 ) fac[++k]= n;
    fac[0]= k;
}

// 计算[1, n]内与m互质的数的个数,容斥定理模板;
int que[1<<10];
int Count(int n, int m){ 
    int g= 0, sum= n;
    que[++g]= 1;
    for(int i=1; i<=fac[0]; ++i){
        int t= g;
        for(int j=1; j<=g; ++j){
            que[++t]= que[j] * fac[i] * -1;
            sum+= n/que[t];
        }
        g= t;
    }
    return sum;
}

// 二分,二分枚举一个答案mid,计算[1, mid]内有多少个数与m互质,让答案与K比较;
int Binary_search(int m, int K){
    int l=1, r= 2000000000, mid;
    while(l<=r){
        mid= (l+r)>>1;
        if( Count(mid, m) >= K ) r= mid-1; /// 二分很巧妙,当出现单元素交集时,则该元素就是所求的解了
        else l= mid+1;
    }
    return l;
}

int main()
{
    int m, K;
    while(scanf("%d%d", &m, &K)!=EOF)
    {
        Div(m);
        int ans= Binary_search(m, K);
        printf("%d\n", ans);
    }
}

原创粉丝点击