您的位置:首页 > 移动开发

POJ 2773 Happy 2006(容斥原理+二分)

2012-10-06 17:20 381 查看
题目链接

题意:找和m互质的第k个数。

容斥原理可以快速求出某个范围内,和m不互斥的个数,显然可以求出某个范围内互质的个数,所以只要取一个很大的end,二分即可,写二分的时候开始按普通的写的,发现不对,要找第一个出现的数才是结果,取end和容斥的模版敲错一点,查数据查出了错,4Y。

#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
#define ll __int64
int prim[1001];
ll judge(ll x,int len)//容斥求出1-x范围内和m的互质的个数
{
int i,j,cat;
ll tem,ans = 0;
for(i = 1;i < 1<<len;i ++)
{
cat = 0;
tem = 1;
for(j = 0;j <= len-1;j ++)
{
if(i&(1<<j))
{
cat ++;
tem *= prim[j];
}
}
if(cat%2)
{
ans += x/tem;
}
else
{
ans -= x/tem;
}
}
return x-ans;
}
int main()
{
int m,k,i,len;
ll end,str,mid;
while(scanf("%d%d",&m,&k)!=EOF)
{
len = 0;
int num = (int)sqrt(m+0.5);
for(i = 2;i <= num;i ++)
{
if(m%i == 0)
{
prim[len++] = i;
while(m%i == 0)
m = m/i;
}
if(m == 1) break;
}
if(m != 1) prim[len++] = m;
str = 1;
end = 1e13;//开始开小了
while(str < end)
{
mid = (str+end)/2;
ll key = judge(mid,len);
if(key < k)
str = mid+1;
else
end = mid;
}
printf("%I64d\n",str);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: