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

题目链接

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

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

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <cmath>
 4 using namespace std;
 5 #define ll __int64
 6 int prim[1001];
 7 ll judge(ll x,int len)//容斥求出1-x范围内和m的互质的个数
 8 {
 9     int i,j,cat;
10     ll tem,ans = 0;
11     for(i = 1;i < 1<<len;i ++)
12     {
13         cat = 0;
14         tem = 1;
15         for(j = 0;j <= len-1;j ++)
16         {
17             if(i&(1<<j))
18             {
19                 cat ++;
20                 tem *= prim[j];
21             }
22         }
23         if(cat%2)
24         {
25             ans += x/tem;
26         }
27         else
28         {
29             ans -= x/tem;
30         }
31     }
32     return x-ans;
33 }
34 int main()
35 {
36     int m,k,i,len;
37     ll end,str,mid;
38     while(scanf("%d%d",&m,&k)!=EOF)
39     {
40         len = 0;
41         int num = (int)sqrt(m+0.5);
42         for(i = 2;i <= num;i ++)
43         {
44             if(m%i == 0)
45             {
46                 prim[len++] = i;
47                 while(m%i == 0)
48                 m = m/i;
49             }
50             if(m == 1) break;
51         }
52         if(m != 1) prim[len++] = m;
53         str = 1;
54         end = 1e13;//开始开小了
55         while(str < end)
56         {
57             mid = (str+end)/2;
58             ll key = judge(mid,len);
59             if(key < k)
60             str = mid+1;
61             else
62             end = mid;
63         }
64         printf("%I64d\n",str);
65     }
66     return 0;
67 }

 

 

posted @ 2012-10-06 17:20  Naix_x  阅读(198)  评论(0编辑  收藏  举报