POJ 2773 Happy 2006 数学题

题目地址:http://poj.org/problem?id=2773


因为k可能大于m,利用gcd(m+k,m)=gcd(k,m)=gcd(m,k)的性质,最后可以转化为计算在[1,m]范围内的个数t。



1、AC代码:

开始的时候从1开始枚举if(gcd(n,i)==1),果断跑了2000ms


#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <string>
#include <vector>
#include <list>
#include <deque>
#include <queue>
#include <iterator>
#include <stack>
#include <map>
#include <set>
#include <algorithm>
#include <cctype>
#include <cfloat>
using namespace std;

typedef __int64 LL;
const int N=1000002;
const LL II=1000000007;
const int INF=0x3f3f3f3f;
const double PI=acos(-1.0);

inline int in()
{
    char ch = getchar();
    int data = 0;
    while (ch < '0' || ch > '9')
    {
        ch = getchar();
    }
    do
    {
        data=data*10+ch-'0';
        ch=getchar();
    }while(ch>='0'&&ch<='9');
    return data;
}

int xh[N];

int gcd(int n,int m)
{
    int t;
    while(m)
    {
        t=n%m;
        n=m;
        m=t;
    }
    return n;
}


int main()
{
    int i,j,n,k;
    xh[1]=1;
    while(cin>>n>>k)
    {
        if(n==1)
        {
            printf("%d\n",k);
            continue;
        }
        int x=1;
        for(i=2;i<n;i++)
        {
            if(gcd(n,i)==1)
                xh[++x]=i;
        }
        int t=k%x,p=(k-1)/x;
        if(t==0)
            t=x;
        printf("%d\n",p*n+xh[t]);
    }
    return 0;
}



2、AC代码

将于m互质的数记录下来。


#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <string>
#include <vector>
#include <list>
#include <deque>
#include <queue>
#include <iterator>
#include <stack>
#include <map>
#include <set>
#include <algorithm>
#include <cctype>
#include <cfloat>
using namespace std;

typedef __int64 LL;
const int N=1000002;
const LL II=1000000007;
const int INF=0x3f3f3f3f;
const double PI=acos(-1.0);

inline int in()
{
    char ch = getchar();
    int data = 0;
    while (ch < '0' || ch > '9')
    {
        ch = getchar();
    }
    do
    {
        data=data*10+ch-'0';
        ch=getchar();
    }while(ch>='0'&&ch<='9');
    return data;
}

int xh[N];
LL pri[N],x;
bool vis[N];

void prime()//求素数
{
    LL i,j;
    x=0;
    memset(vis,false,sizeof(vis));
    for(i=2;i<N;i++)
    {
        if(!vis[i])
            pri[++x]=i;
        for(j=1;j<=x&&pri[j]*i<N;j++)
        {
            vis[pri[j]*i]=true;
            if(i%pri[j]==0)
                break;
        }
    }
}


int main()
{
    LL n,k,i,j;
    prime();
    while(scanf("%I64d%I64d",&n,&k)!=EOF)
    {
        LL q=n,sum=n;
        if(n==1)
        {
            printf("%I64d\n",k);
            continue;
        }
        memset(xh,0,sizeof(xh));
        for(i=1;i<=x&&pri[i]*pri[i]<=n;i++)
        {
            if(n%pri[i]==0)
            {
                sum=sum*(pri[i]-1)/pri[i];
                for(j=1;j*pri[i]<=q;j++)
                    xh[pri[i]*j]=1;//这个地方和上面的可能越界,所以要用__int64
            }
            while(n%pri[i]==0)
            {
                n/=pri[i];
            }
        }
        if(n>1)
        {
            sum=sum*(n-1)/n;
            for(j=1;j*n<=q;j++)
                xh[j*n]=1;
        }
        //sum m以内与m互素的个数
        LL t=k%sum,p=k/sum;
        if(t==0)
        {
            t=sum;
            p--;
        }
        LL temp=0;
        for(i=1;i<=q;i++)
        {
            if(xh[i]==0)
                temp++;
            if(temp==t)
            {
                printf("%I64d\n",p*q+i);
                break;
            }
        }

    }
    return 0;
}


你可能感兴趣的:(数论,数学题)