bzoj3181: [Coci2012]BROJ

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <cmath>
 5 #include <algorithm>
 6 using namespace std;
 7 int n,p,top,list[105],bin[18],num[200005],ans,l,r,mid;
 8 bool bo[15000005],vis[105];
 9 int lowbit(int x){return x&(-x);}
10 int work(int x,int y){
11     long long fuckpps=1;
12     for (int i=1;i<=top;i++){
13         if (x&bin[i-1]) fuckpps=fuckpps*list[i];
14         if (fuckpps>1e9) return 0;
15     }
16     return y/fuckpps*(num[x]%2==0?1:-1);
17 }
18 bool check(int x){
19     x/=p;
20     int sum=0;
21     for (int i=0;i<bin[top];i++){sum+=work(i,x);}
22     return sum>=n;
23 }
24 int main(){
25     int x;
26     cin>>n>>p;
27     if (p>=69){
28         x=1000000000/p;
29         memset(bo,1,sizeof(bo)); bo[1]=1; int cnt=1;
30         if (n==1){
31             printf("%d\n",p);
32             return 0;
33         }
34         for (int i=2;i<=x;i++){
35             if (bo[i]){
36                 if (i<p) for (long long j=1LL*i*i;j<=x;j+=i) bo[j]=0;
37                 else{
38                     cnt++; if (cnt==n){printf("%d\n",i*p);return 0;}
39                 }
40             }
41         }
42         if (cnt<n) puts("0");
43         return 0;
44     }
45     top=0; memset(vis,0,sizeof(vis));
46     for (int i=2;i<p;i++){
47         if (!vis[i]){
48             list[++top]=i;
49         }
50         for (int j=1;j<=top;j++){
51             if (i*list[j]>=p) break;
52             vis[i*list[j]]=1;
53             if (i%list[j]==0) break; 
54         }
55     }
56     bin[0]=1; for (int i=1;i<=top;i++) bin[i]=bin[i-1]<<1;
57     for (int i=1;i<bin[top];i++) num[i]=num[i-lowbit(i)]+1;
58     ans=0; l=1,r=1e9;
59     while (l<=r){
60         mid=(l+r)>>1;
61         if (check(mid)) ans=mid,r=mid-1;
62         else l=mid+1;
63     }
64     printf("%d\n",ans);
65     return 0;
66 }
View Code

链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3181

题意:求最小质因子等于p的第n小的正整数(恰好有n-1个最小质因子等于p且比它
小的正整数)。p一定是质数。若答案超过10^9则输出0。 

做法:当p>=69时,10^9/p可以接受线性算法,我们就找到1~10^9/p中最小质因子>=p的个数,我们可以用筛法实现,具体见代码,比较神奇。

当p<=61时,我们考虑二分答案x,然后容斥即可,复杂度为O(min(10^9/p,2^(小于p的质数个数)LogL))。

posted @ 2016-10-26 10:14  oyzx~  阅读(247)  评论(0编辑  收藏  举报