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;
}

posted on 2013-07-20 11:34  仗剑奔走天涯  阅读(247)  评论(0编辑  收藏  举报

导航