NOIP1999普及组 Cantor表 O(1)复杂度题解

看注释,应该写的很明白

#include<bits/stdc++.h>
using namespace std;
int N,Layer,Last_Layer;
int main(){
	scanf("%d",&N);
	//沿斜线方向给层编号,第i层的最大数字为i(i+1)/2 
	Layer=ceil(sqrt(2*N+0.25)-0.5);//据此使用一元二次方程的求根公式得到层数
	Last_Layer=Layer-1;
	//第i层的数字,分子分母之和为i+1
	//i为奇数时,行从左到右分子依次减小,分母依次增大
	//反之亦然
	if(Layer==1){ //避免Last_Layer出现0的情况 
		printf("1/1\n");return; 
	}
	
	if(Layer%2==1){
		int x=Last_Layer*(Last_Layer+1)/2; //比较距上行末尾之差,判断应该加多少 
		printf("%d/%d\n",Layer+1-(N-x),N-x);
	} else{
		int x=Layer*(Layer+1)/2; //比较距本行末尾之差,判断应该减多少 
		printf("%d/%d\n",Layer-(x-N),x-N+1);
	}
	return 0;
}

整活向:(删除了所有中间变量的一版代码)

#include<bits/stdc++.h>
using namespace std;
int N,Layer,Last_Layer;
int main(){
	scanf("%d",&N);
	if((int)(ceil(sqrt(2*N+0.25)-0.5))%2==1){ 
		printf("%d/%d\n",(int)(ceil(sqrt(2*N+0.25)-0.5))+1-(N-(((int)(ceil(sqrt(2*N+0.25)-0.5))-1)*(((int)(ceil(sqrt(2*N+0.25)-0.5))-1)+1)/2)),N-(((int)(ceil(sqrt(2*N+0.25)-0.5))-1)*(((int)(ceil(sqrt(2*N+0.25)-0.5))-1)+1)/2));
	} else{
		printf("%d/%d\n",(int)(ceil(sqrt(2*N+0.25)-0.5))-(((int)(ceil(sqrt(2*N+0.25)-0.5))*((int)(ceil(sqrt(2*N+0.25)-0.5))+1)/2)-N),((int)(ceil(sqrt(2*N+0.25)-0.5))*((int)(ceil(sqrt(2*N+0.25)-0.5))+1)/2)-N+1);
	}
	return 0;
}
posted @ 2024-08-09 11:20  计算机知识杂谈  阅读(10)  评论(0编辑  收藏  举报