2014计算机学科夏令营上机考试H:Binary Tree(数学规律)

2014计算机学科夏令营上机考试H:Binary Tree(数学规律)
2014计算机学科夏令营上机考试H:Binary Tree(数学规律)

题目大意

模拟一颗二叉树,根结点为(1,1)。对任意结点(a,b),左孩子结点为(a+b,b),右孩子结点为(a,a+b)。
现给出一结点,判断该结点是从根结点分别向左、向右几次分支得到的。

思路分析

方法一: 逆向考虑。对于结点(a,b),若a>b,则该结点为左孩子结点,父亲结点为(a-b,b);否则为右孩子结点,父亲结点为(a,b-a)。则从该结点向上遍历,直至根结点(1,1)。但很不幸,这种直接了当的方法会超时

方法二: 用除法代替减法。对于结点(a,b),若a>b,则该结点为左孩子结点,a/b为向左分支的次数,a更新为a%b;否则该结点为右孩子结点,b/a为向右分支的次数,b更新为b%a。但此处应当注意的是,若a,b之间存在倍数关系,更新之后一方会变为0,这显然与题意不符,所以这种情况要单独考虑。只需要减少一次分支,将该值赋1即可。

代码——方法一(超时)

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;

int main()
{
    freopen("input.txt", "r", stdin);
    int n;
    scanf("%d", &n);
    for(int i=1; i<=n; i++)
    {
        int a, b;
        int left = 0, right = 0;
        scanf("%d %d", &a, &b);
        while(!(a==1 && b==1))
        {
            if(a > b) // 左孩子结点
            {
                left++;
                a = a-b;
            }
            else if(a < b) // 右孩子结点
            {
                right++;
                b = b-a;
            }
        }
        printf("Scenario #%d:\n", i);
        printf("%d %d\n\n", left, right);
    }
    fclose(stdin);

    return 0;
}

代码——方法二

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;

int main()
{
     freopen("input.txt", "r", stdin);
    int n;
    scanf("%d", &n);
    for(int i=1; i<=n; i++)
    {
        int a, b;
        int left = 0, right = 0;
        scanf("%d %d", &a, &b);
        while(!(a==1 && b==1))
        {
            if(a >= b) // 左孩子结点
            {
                if(a%b != 0)
                {
                    left += a/b;
                    a %= b;
                }
                else 
                {
                    left += a/b - 1;
                    a = 1;
                }
            }
            else // 右孩子结点
            {
                if(b%a != 0)
                {
                    right += b/a;
                    b %= a;
                }
                else 
                {
                    right += b/a - 1;
                    b = 1;
                }
            }
        }
        printf("Scenario #%d:\n", i);
        printf("%d %d\n\n", left, right);
    }
    // fclose(stdin);

    return 0;
}