题目描述
现代数学的著名证明之一是 Georg Cantor 证明了有理数是可枚举的。他是用下面这一张表来证明这一命题的:
1/11/1 , 1/21/2 , 1/31/3 , 1/41/4, 1/51/5, …
2/12/1, 2/22/2 , 2/32/3, 2/42/4, …
3/13/1 , 3/23/2, 3/33/3, …
4/14/1, 4/24/2, …
5/15/1, …
…
我们以 Z 字形给上表的每一项编号。第一项是 1/11/1,然后是 1/21/2,2/12/1,3/13/1,2/22/2,…
输入格式
整数�N(1≤�≤1071≤N≤107)。
输出格式
表中的第 �N 项。
样例 #1
样例输入 #1
7
Copy
样例输出 #1
1/4
Copy
题解1
解题思路
可以把上面的数表右转45度,成一金字塔形状,如下所示:
1/1
2/1 1/2
3/1 2/2 1/3
4/1 3/2 2/3 1/4
…… …… …… ……
该金字塔第1行有1个数,第2行有2个数,…,第i行有i个数。并且第i行上的i个分数的分子从i ~ 1,分母从1 ~ i,即第1个分数为i/1,最后一个分数为1/i。
为输出数表中的第N项,先需计算这一项在第几行。设第N项在x行,由于前x-1行共有1+2+3+…+(x-1)项,前x行有1+2+…+x项,因此有:
可以用一个循环计算第n项所在的行数,如下:
for (i=1; i*(i+1)/2<n; i++);
Copy
循环退出后,i*(i+1)/2刚好大于或等于n,因此,i就是第n项所在的行。
第n项在第i行中属于第几项又可以计算出来,公式为:
即n减去前i-1行中的全部项数。
由于是以z字型方法给数表的每项编号,因此当行号为奇数时,编号从左往右进行;当行号为偶数时,编号从右往左进行。
这样,当i为奇数时,第i行的第k项为(i+1-k)/(k);当i为偶数时,第i行的第k项为(k)/(i+1-k)。
AC代码
#include <bits/stdc++.h>
using namespace std;
int main()
{
int i, x, n;
cin >> n;
for (i = 1; i * (i + 1) / 2 < n; i++); //不要忘记这个分号!
x = n - (i * (i - 1) / 2);
if (i % 2 != 0)
printf("%d/%d\n", i + 1 - x, x);
else
printf("%d/%d\n", x, i + 1 - x);
return 0;
}
题解2
思路1
这道题我很久之前做过,那时我还是萌新时代,啃了10年天,然后终于AC了。
我的思路很简单,直接暴力模拟(这道题就是考模拟,1≤�≤1071≤n≤107),我的模拟就是模拟 �−1n−1 次Z字形移动,判断是否到边上和奇数偶数边,费了老死劲了,才搞出来。
#include <bits/stdc++.h>
using namespace std;
int n, x = 1, y = 1;
int main()
{
scanf("%d", &n);
for (int i = 1; i <= n - 1; i++)
{
if ((x + y) % 2 == 0 && y == 1)
{
// 向右
x++;
}
else if ((x + y) % 2 == 1 && x == 1)
{