描述
现代数学的著名证明之一是Georg Cantor证明了有理数是可枚举的。他是用下面这一张表来证明这一命题的: 1/1 1/2 1/3 1/4 1/5 … 2/1 2/2 2/3 2/4 … 3/1 3/2 3/3 … 4/1 4/2 … 5/1 … … 我们以Z字形给上表的每一项编号。第一项是1/1,然后是1/2,2/1,3/1,2/2,…
输入
输入:整数N(1≤N≤10000000)
输出
输出:表中的第N项
样例输入
7样例输出
1/4[分析]题目很简单,规律也不难找到。这类题目其实是数学游戏,在编码之前应该先算一算。 用模拟填表的方法也可以,但数学方法更有意思,求解能力也更强。不难看出,第K个斜行("/"方向)上 每个分数的分子分母之和为K+1,而表的填充顺序正是依次填写每个斜行,因此先算出第N项所在的斜行K。
显然K是满足N<=1+2+3+...+K (1)的最小数。
显然当K为奇数时,分母为N-(1+2+3+..+K-1),K为偶数时分子为N-(1+2+3+..+K-1)。
找K显然可以递推,但是没有意思,我们应该锻炼自己的数学能力,解出不等式(1)。
不等式同解变形为:(K+1)*K>=N*2, K*K+K-N*2>=0
解不等式,取正数区间,得 K>=(-1+sqrt(1+8*N))/2。
例如N=7时K>=(-1+sqrt(1+7*8))/2=3.275
故K=4,分子分母之和为K+1=5,因为K是偶数,分子为N-(1+2+3)=1,故分母为5-1=4
#include<stdio.h> #include<math.h> #include<cstring> int main() { float f; int N,n,zi,mu; while(~scanf("%d",&N)) { f=(-1+sqrt(1+8*N))/2; n = (int)f; if(f - (float)n != 0) n +=1; if(n%2 == 0) { zi = N - (n-1)*n/2; mu = n+1-zi; } else { zi = n*(n+1)/2 -N + 1; mu = n+1-zi; } printf("%d/%d",zi,mu); } return 0; }