Detailed explanation of Luogu Thousand Questions | P1014 [NOIP1999 Popularization Group] Cantor Table [C++, Java Language]

Blogger homepage: Yu·Xiansheng

Column address: Detailed Explanation of Thousand Questions in Luogu

Table of contents

Question description

Input format

Output format

Input and output samples

Analysis:

C++ source code:

C++ source code 2:

C++ source code 3:

Java source code:


------------------------------------------------------------------------------------------------------------------------------- 

 ------------------------------------------------------------------------------------------------------------------------------- 

Question description

One of the famous proofs in modern mathematics is Georg Cantor's proof that rational numbers are enumerable. He used the following table to prove this proposition:

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, …

We number each item in the table above in a zigzag. The first item is 1/1, then 1/2, 2/1, 3/1, 2/2,…

 ------------------------------------------------------------------------------------------------------------------------------- 

Input format

Integer N (1≤N≤107).

 ------------------------------------------------------------------------------------------------------------------------------- 

Output format

Item N in the table.

 ------------------------------------------------------------------------------------------------------------------------------- 

Input and output samples

Input #1

7

Output #1

1/4

 ------------------------------------------------------------------------------------------------------------------------------- 

Analysis:

 update: Obviously, this kind of program is not the shortest. Many dalaodalao have pointed out in the comments, and the time complexity is not excellent, but at that time, I felt an inexplicable confidence  . As for how to do it, the comment area also made it clearer. Now, so the comments don't need to provide ideas for suppressing the line anymore.

update: First we observe that the number in row ii and column jj is i/ji/j, which is the first thing to find.

Because the title requires a Z-shaped number

Let's look at the table in the title:

1/1,1/2,1/3 ……

2/1,2/2,2/3 ……

After the zigzag number (turn your head 45 degrees to the left):

First row: 1/1 (number 1)

Second row: 1/2 (No. 2) 2/1 (No. 3)

Third row: 1/3  (No. 6)  2/2 (No. 5)  3/1 (No. 4)

\uparrow↑ The observation method is easy to find that each line is 1 more than the previous line.

The while loop in the code is to determine which line and position it is after the number through loop enumeration.


(This question can be answered with or without this optimization, but the comments pointed out that my time complexity is not good enough, so I mention this optimization. If you don’t want to read it, you can just skip the content after the next dividing line.)

But in fact, we can directly conclude that the optimization time complexity is optimized from O(n) to O(1), so we must consider the sum of arithmetic sequences.

Formula: S=2n(an​+a1​)​

Therefore, it is obvious that after Z-shaped sorting, the number n in the k-th row satisfies:

\frac{k(k-1)}{2} < n \le \frac{k(k+1)}{2}

 ------------------------------------------------------------------------------------------------------------------------------- 

C++ source code:

#include<cstdio>
int main()
{
    int n;scanf("%d",&n);
    int t=1,ans=0;//t是表示下一次跳到下一次的距离,ans是表示第几层
    while(1)
    {
        if(n>t){n-=t;ans++;t++;}//printf("%d\n",ans);
        else if(n==t&&ans%2==0){printf("1/%d",ans+1);break;}
        //如果在n==t,并且为偶数层,就在第一行 第ans+1个 
        else if(n==t&&ans%2!=0){printf("%d/1",ans+1);break;}
        //如果在n==t,并且为奇数层,就在第ans+1行 第一个
        else if(n<t&&ans%2!=0){printf("%d/%d",ans+n-t+1,t-n+1);break;}
        //如果在n<t,并且为奇数层,t-n+1表示该层最后一个往后走n-1步,ans+n-t+1示该层最后一个往上走t-1步 
        else if(n<t&&ans%2==0){printf("%d/%d",t-n+1,ans+n-t+1);break;}
        // 如果在n<t,并且为偶数层,t-n+1表示该层最后一个往上走n-1步,ans+n-t+1示该层最后一个往后走t-1步 
    }
    return 0;
}

 ------------------------------------------------------------------------------------------------------------------------------- 

C++ source code 2:

#include<bits/stdc++.h>
using namespace std;
int main()
{
    int i = 0, n, s = 0, x, y;//s:按整条斜线走过的格子的末尾编号 
    cin >> n;
    while(s < n)//s >= n时,说明编号为n的格子在刚才加的第i斜线之中 
    {
        i++;
        s += i;
    }
    s -= i;//此时确定n在第i条斜线上 
    if(i % 2 == 1)//从i/1出发向右上遍历,找编号为n的格子 
    {
        x = i, y = 1, s++;
        while(s < n)//s == n时,x,y的值即为编号为n的格子的坐标 
            x--, y++, s++;
    }
    else//从1/i出发向左下遍历,找编号为n的格子 
    {
        x = 1, y = i, s++;
        while(s < n)//s == n时,x,y的值即为编号为n的格子的坐标
            x++, y--, s++;
    }
    cout << x << '/' << y;
    return 0;
}

 ------------------------------------------------------------------------------------------------------------------------------- 

C++ source code 3:

#include<bits/stdc++.h>
using namespace std;
int main()
{
    int i = 0, n, s = 0, x, y, l;
    cin >> n;
    while(s < n)//看第n格子是否在第i斜线上 
    {
        i++;
        s += i;
    }
    s -= i;
    l = n-s;//在第i斜线数几个 
    if(i % 2 == 1)//从i/1出发 
    {
      	x = i+1-l;//i-x+1=l
		y = l; 
    }
    else//从1/i出发 
    {
        x = l;//x-1+1 = l
        y = i+1-l;//i-y+1=l
    }
    cout << x << '/' << y;
    return 0;
}

 ------------------------------------------------------------------------------------------------------------------------------- 

Java source code:

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int position = scanner.nextInt();
        int sum, end = 1;
        while (true) {
            sum = (1 + end) * end / 2;
            if (position <= sum) break;
            ++ end;
        }
        sum -= position;
        if (end%2 == 0) { // 偶数
            // 大数在前
            System.out.println((end-sum) + "/" + (1+sum));
        } else { // 奇数
            // 大数在后
            System.out.println((1+sum) + "/" + (end-sum));
        }
    }

 ------------------------------------------------------------------------------------------------------------------------------- 

Guess you like

Origin blog.csdn.net/djfihhfs/article/details/127720708