POJ 2773

不经意看见dis后的“mod”一词后,瞬间有了思路,点进去看,却发现别人想的和我的不一样——!

我是这样想的,利用的是剩余系+欧几里德带余除法的性质。

若两者GCD=1,则必有除数和余数GCD=1.于是,求出除数剩余系,再在原位置加上被除数的倍数得到第k个数.

#include <iostream>
#include <cstdio>
#include <algorithm>
#define N 1000005
using namespace std;

const int Np=1005;

bool iscoprime[N],isprime[Np];
int coprime[N],cp,prime[Np],np,fac[100],fp;

void initial(){
	memset(isprime,true,sizeof(isprime));
	np=0;
	for(int i=2;i<Np;i++){
		if(isprime[i]){
			prime[np++]=i;
			for(int j=i*i;j<Np;j+=i)
			isprime[j]=false;
		}
	}
}

void Fcoprime(int m){
	int p=m;
	fp=0;
	for(int i=0;i<np&&prime[i]*prime[i]<=p;i++){
		if(p%prime[i]==0){
			while(p%prime[i]==0)
			p/=prime[i];
			fac[fp++]=prime[i];
		}
	}
	if(p>1) fac[fp++]=p;
	
	memset(iscoprime,true,sizeof(bool)*(m+2));
	cp=1;
	for(int i=0;i<fp;i++){
		for(int k=1;k*fac[i]<m;k++)
		iscoprime[k*fac[i]]=false;
	}
	coprime[0]=0;
	for(int i=1;i<m;i++)
	if(iscoprime[i]){
		coprime[cp++]=i;
	}
}

int main(){
	initial();
	int m,k;
	while(scanf("%d%d",&m,&k)!=EOF){
		if(m==1){
			printf("%d\n",k);
			continue;
		}
		Fcoprime(m);
		__int64 ans;
		int T=k/(cp-1);
		if(k%(cp-1)==0){
			ans=(__int64)(T-1)*(__int64)m+(__int64)coprime[cp-1];
		}
		else 
			ans=(__int64)T*(__int64)m+(__int64)coprime[k%(cp-1)];
		printf("%I64d\n",ans);
	}
	return 0;
}

  

posted @ 2014-10-02 10:08  chenjunjie1994  阅读(291)  评论(0编辑  收藏  举报