poj 2773 Happy 2006(容斥原理)

来源:互联网 发布:美图里的蜡笔软件 编辑:程序博客网 时间:2024/06/15 16:03

题意:求和m互质的第k个数是多少。

思路:假设我们要求的数是n,那么如何求n之前有多少个数和m互质呢?这个问题直接算不好算,根据减法原理,我们可以求出和m不互质的数,然后用n减去,就可以得到和n互质的数的个数了。假设和m的质因子分别为q1,q2,q3……那么能整除q1的数就有n/q1个,能整除q2的数有n/q2个……将这些数加起来,但是会有重复的,比如能被q1和q2同时整除的被加了两次,这部分要减去,然后又发现减多了,加上……这就是容斥原理的基本过程。这个过程可以通过dfs解决,对于每个组合如果因子的个数是奇数个,那么减去,否则加上。接下来只要二分求n就可以了。


代码:


#include<iostream>#include<cstdio>#include<cstring>#include<string>#include<algorithm>#include<map>#include<queue>#include<stack>#include<set>#include<cmath>#include<vector>#define inf 0x3f3f3f3f#define Inf 0x3FFFFFFFFFFFFFFFLL#define eps 1e-9#define pi acos(-1.0)using namespace std;typedef long long ll;int factor[20],tot;ll M,K,sum;void fenjie(ll n){    tot=0;    int m=sqrt(n+0.5);    for(int i=2;i<=m;++i)    {        if(n%i==0)        {            factor[tot++]=i;            while(n%i==0) n/=i;        }    }    if(n>1) factor[tot++]=n;}void dfs(int pos,ll now,int cnt,ll x){    if(pos==tot)    {        if(now==1) return ;        if(cnt&1) sum+=x/now;        else sum-=x/now;        return ;    }    dfs(pos+1,now*factor[pos],cnt+1,x);    dfs(pos+1,now,cnt,x);}bool test(ll x){    sum=0;    dfs(0,1,0,x);    return (x-sum)>=K;}int main(){    //freopen("in.txt","r",stdin);    //freopen("out.txt","w",stdout);    while(cin>>M>>K)    {        fenjie(M);        ll l=1,r=Inf,m;        while(l<r)        {            m=(l+r)>>1;            if(!test(m))                l=m+1;            else r=m;        }        cout<<l<<endl;    }    return 0;}

0 0