算法竞赛入门经典:第五章 基础题目选解 5.9 Cantor数

/*
Cantor的数表:
如下列数,第一项是1/1,第二项是1/2,第三项是2/1,第四项是3/1,第五项是2/2,......。
输入n,输出第n项。
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
(本质上是一个折线)

输入:
3
14
7
12345
输出:
2/1
2/4
1/4
59/99

关键:
这是一个折线,需要确定折线的走向公式与数字之间的关系,用数字反映折线
第1条折线 1个元素
  2       3
  n,      =(n+1)*n/2个元素
  确定n是在 <=s(k) = (k+1)*k/2的最小k,第k条斜线上,然后n是该斜线上倒数第s(k)+1-n个元素,因为最后一个元素是倒数第一个元素i/(k+1-i)。属于数学归纳法
*/

/*
关键:
1 确定n是在 <=s(k) = (k+1)*k/2的最小k,第k条斜线上,然后n是该斜线上倒数第s(k)+1-n个元素,因为最后一个元素是倒数第一个元素i/(k+1-i)。属于数学归纳法
2 if(k % 2 != 0)//奇数从下向上,上面大,下面的分母应该大,用k+1-i,倒数第一是最大分母,例如i=1,k=5,第五斜线最后一个元素分母为5
  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

*/

#include <stdio.h>
#include <stdlib.h>

void cantor(int n)
{
	//枚举求斜线k的值
	int k;
	for(k = 1 ; ;k++)
	{
		if(n <= (k+1)*k/2 && n > (k-1)*k/2)
		{
			break;
		}
	}
	int iSum = (k+1)*k/2;
	int i = iSum + 1 -n;
	if(k % 2 != 0)//奇数不需要转换,奇数从下向上,上面大,下面的分母应该大,用k+1-i,倒数第一是最大分母,例如i=1,k=5,第五斜线最后一个元素分母为5
	{
		printf("%d/%d\n",i,(k+1-i));
	}
	else//偶数斜线,从上向下,最后一个元素分母最小,因此分母为i
	{
		printf("%d/%d\n",(k+1-i),i);
	}
}

int main(int argc,char* argv[])
{
	int n;
	while(EOF != scanf("%d",&n))
	{
		cantor(n);
	}
	system("pause");
	return 0;
}

你可能感兴趣的:(算法竞赛入门)