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

浙公网安备 33010602011771号