題意: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 }
其實在比賽中是想到了這個想法的,但沒有很好的估計上界,在2e7範圍內有至少127w個素數.上界2e7就夠了.get
其次還有一個問題,在比賽中我在想這樣一個問題,我check的mid若是與p知足gcd(p,mid)!=1該怎麼辦,其實不會有這個問題, l....mid l爲離mid最近且gcd(l,p)=1,他們中間的數與p互素的數都是同樣的.咱們至關於二分找知足條件的最小值.it
關於素數計數其實還有一個東西叫素數計數函數,寫起來會簡單一些.event