POJ2773

题目大意

给定两个数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;
}
原文地址:https://www.cnblogs.com/zjbztianya/p/3202162.html