容斥原理 POJ2773

Happy 2006

容斥原理+分解素数因子

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;
}
原文地址:https://www.cnblogs.com/zhang1107/p/2829195.html