zoukankan      html  css  js  c++  java
  • P1014 Cantor表

    漂亮小姐姐点击就送:https://www.luogu.org/problemnew/show/P1014

     

    题目描述

    现代数学的著名证明之一是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项

    输入输出样例

    输入样例#1: 复制
    7
    
    输出样例#1: 复制
    1/4



    // luogu-judger-enable-o2
    //Cantor表的二分log做法
    //可以知道,第i个对角线上一共有i个数
    //那么,前i条对角线上就有1+2+3+4+...+i-1+i个数
    //也就是i + (1 + i-1) + (2 + i-2) + (3 + i-3) + ((i/2)-1 + (i/2)+1)+ i/2个数
    //也就是 i*((i/2)-1) + i + i/2个数
    //把i提出来,就变成了 i*((i-2+2+1)/2)
    //也就是 i*(i+1)/2
    
    //所以,二分一个mid,如果mid*(mid-1)/2<n的话
    //说明在第i条斜线之后,否则在之前或在第i条斜线上 
    //找到了第n个数所处的斜线之后,再找它在斜线上的位置
    //奇数斜线从左下往右上走,偶数斜线从右上往左下走
    //这条斜线的之钱有第i*(i-1)/2个数,
    //所以我们要找的就是这条线上第n - i*(i-1)/2个数
    //让a = n - i*(i-1)/2 
    //奇数线就输出i-a+1 / a
    //偶数线就输出 a / i-a+1
    
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    
    int n;
    
    int main()
    {
        scanf("%d",&n);
        int l=1,r=n,mid;
        while(l<r)
        {
            mid=l+r>>1;
            if(mid*(mid+1)/2<n)
                l=mid+1;
            else
                r=mid;
        }
        int a=n-r*(r-1)/2;
        if(r&1)
            printf("%d/%d",r-a+1,a);
        else
            printf("%d/%d",a,r-a+1);
        return 0;
    }
  • 相关阅读:
    回溯算法
    回溯算法
    回溯算法
    回溯算法思想
    贪心算法
    C#多线程操作界面控件的解决方案
    jQuery教程
    html css JavaScript网页渲染
    jQuery与JavaScript与ajax三者的区别与联系
    asp.net MVC中form提交和控制器接受form提交过来的数据
  • 原文地址:https://www.cnblogs.com/lovewhy/p/8666096.html
Copyright © 2011-2022 走看看