UVA11327 Enumerating Rational Numbers
UVA11327 Enumerating Rational Numbers
0x01 题意
给出了一段代码:
for d = 1 to infinity do
for n = 0 to d do
if gcd(n,d) = 1 then print n / d
输出该程序输出的第\(k\)项
0x02 解
瞪眼法看出来,分母是某个数时,分子是与这个数互质的所有数,顺序从小到大
要求第\(k\)项,可以预处理出来欧拉函数的前缀和,二分找\(k\)在哪个区间里,再暴力求分子就好辣
0x03 码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1000100;
bool notp[N];
int cnt=0,phi[N],pri[N];
void getphi(int n){
cnt=0;
notp[1]=1,phi[1]=1;
for(int i=2;i<=n;i++){
if(!notp[i]) pri[++cnt]=i,phi[i]=i-1;
for(int j=1;j<=cnt&&pri[j]*i<=n;j++){
notp[i*pri[j]]=1;
if(i%pri[j]==0){phi[pri[j]*i]=phi[i]*pri[j];break;}
else phi[pri[j]*i]=phi[i]*(pri[j]-1);
}
}
}
int gcd(int a,int b){
return b?gcd(b,a%b):a;
}
signed main(){
int k;
cin>>k;
getphi(200000);
for(int i=1;i<=200000;i++) phi[i]+=phi[i-1];
while(k){
if(k<=2){printf("%lld/1\n",k-1);cin>>k;continue;}
k-=2;
int r=upper_bound(phi+1,phi+200000,k)-phi;
k-=phi[r-1];
int i;
for(i=1;i<=r&&k>=0;i++) if(gcd(i,r)==1) k--;
printf("%lld/%lld\n",i-1,r);
cin>>k;
}
return 0;
}