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;
}
posted @ 2021-03-03 21:29  wsy_jim  阅读(78)  评论(0编辑  收藏  举报