cf920G List Of Integers 二分+容斥

題意:c++

求第k個大於x且與p互素的數,其中k,p,x<=1e6.ide

思路:函數

二分+容斥.spa

二分這個數是mid,而後去檢驗(x,mid]間有多少個與p互素的數.能夠用容斥算出[1,mid]和[1,x]區間內有多少與p互質的數.code

代碼:blog

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int MAXN=20;
 4 int prime[MAXN],tot;
 5 int x,p,k;
 6 int getCnt(int num){
 7     int res=num;
 8     for(int i=1;i<(1<<tot);++i){
 9         int flag=0;
10         int muti=1;
11         for(int j=0;j<tot;++j){
12             if((1<<j)&i){
13                 ++flag;
14                 muti*=prime[j];
15             }
16         }
17         if(flag&1)res-=num/muti;
18         else res+=num/muti;
19     }
20     return res;
21 }
22 int qwq;
23 bool isok(int mid){
24     //printf("getCnt(%d)=%d -%d=%d\n",mid,getCnt(mid),qwq,getCnt(mid)-qwq);
25     return getCnt(mid)-qwq>=k;
26 }
27 int main(){
28     int t;scanf("%d",&t);
29     while(t--){
30         scanf("%d%d%d",&x,&p,&k);
31         if(p==1){
32             printf("%d\n",x+k);
33             continue;
34         }
35         int tmp=p;
36         tot=0;
37         for(int i=2;i*i<=tmp;++i){
38             if(tmp&&tmp%i==0)prime[tot++]=i;
39             while(tmp&&tmp%i==0)tmp/=i;
40         }
41         if(tmp>1)prime[tot++]=tmp;
42 
43         qwq=getCnt(x);
44     //    printf("qwq=%d\n",qwq);
45         int lo=x,hi=2e7;
46         while(hi-lo>1){
47             int mid=(hi+lo)/2;
48             if(isok(mid))hi=mid;
49             else lo=mid;
50         }
51         printf("%d\n",hi);
52     }
53     return 0;
54 }
View Code

 

其實在比賽中是想到了這個想法的,但沒有很好的估計上界,在2e7範圍內有至少127w個素數.上界2e7就夠了.get

其次還有一個問題,在比賽中我在想這樣一個問題,我check的mid若是與p知足gcd(p,mid)!=1該怎麼辦,其實不會有這個問題, l....mid l爲離mid最近且gcd(l,p)=1,他們中間的數與p互素的數都是同樣的.咱們至關於二分找知足條件的最小值.it

關於素數計數其實還有一個東西叫素數計數函數,寫起來會簡單一些.event

相關文章
相關標籤/搜索