nyoj题目链接:
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;
}