且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

POJ 2773 欧拉函数

更新时间:2022-08-13 16:40:04

题意:让求从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;
}