容斥原理+分解素数因子
View Code
//POJ2773 const int MM = 1100000; typedef __int64 int64; const int64 maxint = 0x3f3f3f3f; int64 N,M; bool isp[MM]; int64 tp[MM],mm; int64 p[MM],cnt; void get_prime() { int64 i,j,k; memset(isp,true,sizeof(isp)); isp[0]=isp[1]=false; for(i=2;i<1005;i++) { if(isp[i]) { for(j=i*i;j<MM;j+=i) isp[j]=false; } } cnt=0; for(i=2;i<MM;i++) if(isp[i]) p[cnt++]=i; } //24 1 5 7 11 13 17 19 23 void get_init() { int64 i,j,k,tmp; mm=0; tmp=N; for(i=0;i<cnt&&tmp>1;i++) { if(tmp%p[i]==0) { tp[mm++]=p[i]; while(tmp%p[i]==0) tmp/=p[i]; } } } //容斥 int64 gao(int64 n) { int64 i,j,k,ret,ans=n; for(i=1;i<(1<<mm);i++) { for(k=j=0,ret=1;j<mm;j++) { if((i>>j)&1) { ret=lcm(ret,tp[j]); k++; } } if(k&1) ans-=n/ret; else ans+=n/ret; } return ans; } //二分枚举答案 void solve() { int64 i,j,k,ll=1,rr=maxint,mid,tmp,ans,sum; get_init(); while(ll<=rr) { mid=(ll+rr)>>1; tmp=gao(mid); if(tmp>=M) ans=mid,rr=mid-1; else ll=mid+1; } printf("%lld\n",ans); } int main() { get_prime(); while(scanf("%lld%lld",&N,&M)!=EOF) solve(); return 0; }