poj 2773 Happy 2006

#include <stdio.h>
#include <string.h>
#define INF 1000010
int f[INF];   //f[n]记录n是否为素数,0时为素数
//int prime[INF];
int s[INF];
void init()
{
    int i,j,k=0;
    for(i=2;i*i<=INF;i++)
    {
        for(j=i*i;j<INF;j=j+i)
        f[j]=1;
    }
   // for(i=2;i<=INF;i++)
   // if(f[i]==0)
   //     prime[k++]=i;
}
int euler(int n) //欧拉函数
{
    int i,res=n;
    for(i=2;i*i<=n;i++)
    {
        if(n%i==0)
        {
            res=(res/i)*(i-1);
            while(n%i==0)
            n/=i;
        }
    }
    if(n!=1)
           res=(res/n)*(n-1);
    return res;
}
int find(int n,int t)
{
    int m,i,j,l,k=0,e[1000];
    i=2;
    m=n;
    while(m!=1&&i<m)
    {
        if(m%i==0)
        {
            e[k++]=i;
            while(m%i==0)
            m=m/i;
            if(f[m]==0)
            {
                if(m!=1)
                e[k++]=m;
                break;
            }
        }
        i++;
    }
    //找到所有不互质的数
    memset(s,0,sizeof(s));
    for(i=0;i<k;i++)
    for(j=0;j<k;j++)
    {
        for(l=e[i];l<=n;l=l+e[i])
        s[l]=1;
    }
    for(i=1,j=0;i<n;i++)
    {
        if(s[i]==0)
        {
            j++;
            if(j==t)
            return i;
        }
    }
}
int main()
{
    init();
    int n,m;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        int i,j,k,s,t;
        t=euler(n);
        i=m/t;
        j=m%t;
        if(j==0)
        k=n*(i-1)+find(n,t);
        else
        k=n*i+find(n,j);
        printf("%d\n",k);
    }
    return 0;
}
//m,n互质,则m+k*n必定和n互质,用辗转相除最大公约数gcd(m+n*k,n)=gcd(n,(n*k+m)%n)=gcd(n,m%n)=gcd(m,n);
//m,n不互质,则m+k*n必定和n不互质,证明同上

你可能感兴趣的:(欧拉函数)