题意:给你x、p、k三个数,让你求大于x的第k个与p互素的数?
思路:求出p的质因子,然后求小于等于x的与p互质的个数求出为j,题意就相当于求大于0的第k+j个与p互素的数了,二分枚举答案,求小于等于某一个数与p互质的个数使用容斥原理计算得出。
代码:
#include<cstdio> #include<iostream> #include<string> #include<cstring> #include<algorithm> #include<cmath> #define inf 1000000007 using namespace std; typedef long long ll; int x, p, k; int prime[1000005], ji=0, shu[105], jj=1; int pa[1000005]; int Solve(int x,int a,int type) { if(a==jj) { return x * type; } else { return Solve(x,a+1,type) + Solve(x/shu[a],a+1,type * -1); } } int main() { int t; scanf("%d",&t); pa[0]=pa[1]=1; for(int i=2; i*i<=1000000; i++) { if(!pa[i]) { prime[ji++]=i; for(int j=i*i; j<=1000000; j=j+i) { pa[j]=1; } } } for(int i=1000;;i++) { if(!pa[i]) { prime[ji++]=i; break; } } while(t--) { jj=1; scanf("%d%d%d",&x,&p,&k); for(int i=0; prime[i]*prime[i]<=p; i++) { int flag=1; while(p%prime[i]==0) { if(flag) { flag=0; shu[jj++]=prime[i]; } p=p/prime[i]; } } if(p>1) shu[jj++]=p; if(p==1&&jj==0) { printf("%d\n",x+k); continue; } k=k+Solve(x,1,1); int l=x, r=1000000005; while(r-l>1) { int mid=(l+r)/2; if(Solve(mid,1,1)>=k) { r=mid; } else { l=mid; } } cout << r << endl; } return 0; }