nyoj 762第k个互质数 poj 2773Happy 2006

本文介绍了如何通过容斥原理和二分查找算法解决查找第k个互质数的问题,提供了代码实现,并对比了在不同在线评测平台上的表现差异。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

nyoj题目链接:

http://acm.nyist.net/JudgeOnline/problem.php?pid=762

nyoj和poj题意一样,就是查找第k个互质数,
nyoj应该用容斥原理+二分查找,这道题在poj很容易AC,本来poj时间限制就长,而且后台水,比如我自己写的代码在poj32ms,在nyoj就一直TLE。
容易想到的方法就是二分查找数字,然后判断这个数字和n有多少个互质数,至于怎么判断,可以用容斥原理。(之前自己用的是递归,看了

http://blog.youkuaiyun.com/lyhvoyage/article/details/41047009

这位大牛的博客才知道原来容斥也可以用两层for循环来判断,而且写起来也比递归要方便很多)
代码:

#include<stdio.h>
int a[50],b[1010];  //a数组用来保存n的质因子,其中a[0]表示质因子个数
void finds(int n)  //查找n的质因子个数
{
    int i,j=0;
    for(i=2; i*i<=n; ++i)
        if(n%i==0)
        {
            while(n%i==0)
                n/=i;
            a[++j]=i;
        }
    if(n>1) a[++j]=n;
    a[0]=j;
}
int num(int n)  //根据容斥原理来判断Search中的mid含有多少个与n互质的数
{
    int g=0,sum=n,i,j,t;
    b[++g]=1;
    for(i=1; i<=a[0]; i++)
    {
        t=g;
        for(j=1; j<=g; j++)
            b[++t]=b[j]*a[i]*-1,sum+=n/b[t];
        g=t;
    }
    return sum;
}
int Search(int n,int m) //二分定位含有k个互质数的那个数
{
    int mid,l=1,r=2000000000,s;//假设右边界最大为2e9
    while(l<=r)
    {
        mid=(l+r)/2;
        s=num(mid);
        if(s<m)
            l=mid+1;
        else
            r=mid-1;
    }
    return l;
}
int main()
{
    int n,k;
    while(scanf("%d%d",&n,&k)!=EOF)
    {
        finds(n);
        int ans=Search(n,k);
        printf("%d\n",ans);
    }
}

容斥模板:(a[]表示需要判断的数字,其中a[0]表示有多少个,另开一个b的数组,大小大致为a[0]*(a[0]+1)/2,输入n表示判断n,输出的sum表示n内有多少个与数组a[]里面的数互质的个数);

int num(int n)  //根据容斥原理来判断Search中的mid含有多少个与n互质的数
{
    int g=0,sum=n,i,j,t;
    b[++g]=1;
    for(i=1; i<=a[0]; i++)
    {
        t=g;
        for(j=1; j<=g; j++)
            b[++t]=b[j]*a[i]*-1,sum+=n/b[t];
        g=t;
    }
    return sum;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值