POJ 2773 happy2006 (素因子分解+容斥原理+二分)

各种拙计,比赛时连暴力版本都没写出来,too weak :-(

参考代码:http://blog.csdn.net/kg_second/article/details/8034188

#include <cstdio>
#include <cstring>
using namespace std;
const int maxn =1000+5;
#define MAX 1000000000
bool hash[maxn];
int prime[maxn];
int a[11];
int n,k,cnt,K;
void init()
{
    cnt=0;
    memset(hash,0,sizeof(hash));
    for(int i = 2 ;i < maxn;i ++)
        if(!hash[i]){
            prime[cnt++] = i;
            for(int j= i+i ;j < maxn; j +=i)
                hash[j] = 1;
        }
}
void getprime()///素因子分解
{
    int tmp = n;
    k = 0;
    for(int i = 0;i < cnt&& prime[i] * prime[i] <= n; i++)
        if(tmp%prime[i]==0){
            a[k++] = prime[i];
            while(tmp % prime[i] == 0)
                tmp /= prime[i];
        }
    if(tmp != 1) a[k++] = tmp;
}
int judge(int num)///求出num前与num互质的元素个数
{
    int sum=0;
    for(int i = 1; i < (1<<k); i++)///利用容斥原理
    {
        int tmp = 1,t = 0;
        for(int j = 0;j < k; j++)
            if((1 << j) & i){
                t++;
                tmp *= a[j];
            }
        if(t%2) sum += num/tmp;
        else sum -= num/tmp;
    }
    return num-sum;
}
int main()
{
    init();
    while(~scanf("%d%d",&n,&K))
    {
        getprime();
        int l=1,r=MAX,mid,ans;
        while(l<=r)
        {
            mid=(l+r)>>1;
            int pt=judge(mid);
            if(pt>=K){
                if(pt==K) ans=mid;
                r=mid-1;
            }
            else l=mid+1;
        }
        printf("%d\n",ans);
    }
    return 0;
}


你可能感兴趣的:(POJ 2773 happy2006 (素因子分解+容斥原理+二分))