POJ 2773 欧拉函数

来源:互联网 发布:mac怎么进硬件检测模式 编辑:程序博客网 时间:2024/06/06 13:20

题意:让求从1开始第k个与m互素的数。

求最大公约数的第一步是用大数对小数取余。gcd(a,b)==gcd(a%b,b),进一步推出gcd(a,b)==gcd(a+b, b)。也就是说,当求出了1~m间与m互质的数之后,把这些数加上m就可以得到m~2m间的与m互质的数。而且m~2m间不会有某个与m互质的数被漏掉。因为如果m<=a<=2m,且gcd(a, m)==1,那么gcd(a - m, m)必然等于1。也就是必然有个在1~m间的数a-m,可以通过加m的方式得到a。所以与m互质的数是有周期性的。我们只需要求出第一个周期即可。

#include <iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<cmath>using namespace std;long long phi(long long n){    long long rea=n;    for(int i=2; i*i<=n; i++)        if(n%i==0)        {            rea=rea-rea/i;            do                n/=i;            while(n%i==0);        }    if(n>1)        rea=rea-rea/n;    return rea;}long long gcd(long long a,long long b){    if(!b)        return a;    return gcd(b,a%b);}int main(){    long long m,k,ans;    while(~scanf("%I64d%I64d",&m,&k))    {        if(m==1)        {            printf("%I64d\n",k);            continue;        }        int b=phi(m),now=k/b;        if(k%b==0)now--;        for(long long i=now*m,num=0; i<(now+1)*m; i++)        {            if(gcd(i,m)==1)                num++;            if(num+now*b==k)            {                ans=i;                break;            }        }        printf("%I64d\n",ans);    }    return 0;}


原创粉丝点击