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