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