POJ2773 - Happy 2006(欧拉函数)

题目大意

给定两个数m,k,要求你求出第k个和m互质的数

题解

我们需要知道一个等式,gcd(a,b)=gcd(a+t*b,b)

证明如下:gcd(a+t*b,b)=gcd(b,(a+t*b)%b)=gcd(b,a%b)=gcd(a,b)

所以区间[1,m-1]与m互质的个数等于区间[1+t*m,(t+1)*m-1]与m互质的个数,即都等于phi(m),那么答案就等于第k%phi(m)个与m互素的值p+m*(k/phi(m))

代码:

#include<iostream>

#include<cstdio>

#include<cmath>

#include<cstring>

using namespace std;

typedef long long LL;

#define MAXN 1000000

int check[MAXN+5];

int euler_phi(int n)

{

    int m=(int)sqrt(n+0.5);

    int ans=n,k=n;

    memset(check,false,sizeof(check));

    for(int i=2; i<=m; i++)

        if(n%i==0)

        {

            ans=ans/i*(i-1);

            for(int j=1; i*j<=k; j++)

                check[i*j]=true;

            while(n%i==0)n/=i;

        }

    if(n>1)

    {

        ans=ans/n*(n-1);

        for(int j=1; n*j<=k; j++)

            check[n*j]=true;

    }

    return ans;

}

int main(void)

{

    int m,k,ans,cnt,t,i;

    while(cin>>m>>k)

    {

        ans=euler_phi(m);

        cnt=0;

        if(k%ans==0)

            t=k/ans-1;

        else

            t=k/ans;

        k=k-ans*t;

        for(i=1; i<=m; i++)

        {

            if(!check[i])

                cnt++;

            if(cnt==k) break;

        }

        cout<<i+m*t<<endl;

    }

    return 0;

}

你可能感兴趣的:(APP)