题意:给一个这样的二叉树,每个节点用一对数(a,b)表示,根节点为(1,1)。设父亲为(a,b),左儿子(a+b,b),右儿子(a,a+b)。
给几组数据,(i,j),求从根节点到(i,j)节点需要向左子树走多少次,往右子树多少次。
思路:可以发现:当i>j时,(i,j)为左儿子;当i<j时,(i,j)为右儿子。
设父节点为(a,b),往左子树需要走l次,往右子树需要走r次,那么:
1.i>j时:i=a+b,j=b -> a=i-j,b=j l++;
2.i<j时:i=a,j=a+b -> a=i,b=j-i r++;
当然,写代码时不能一个一个减,会超时的。一次性把能减的都减去。
#include <iostream> #include <stdio.h> /* AC 给一个这样的二叉树,每个节点用一对数(a,b)表示,根节点为(1,1)。设父亲为(a,b),左儿子(a+b,b),右儿子(a,a+b)。 给几组数据,(i,j),求从根节点到(i,j)节点需要向左子树走多少次,往右子树多少次。 思路:可以发现:当i>j时,(i,j)为左儿子;当i<j时,(i,j)为右儿子。 设父节点为(a,b),往左子树需要走l次,往右子树需要走r次,那么: 1.i>j时:i=a+b,j=b -> a=i-j,b=j l++; 2.i<j时:i=a,j=a+b -> a=i,b=j-i r++; */ using namespace std; int main() { int t; scanf("%d",&t); long long i,j; int l,r; for(int w=1;w<=t;w++){ l=0;r=0; scanf("%lld%lld",&i,&j); while(1){ if(i==1 && j==1) break; /* 若i>j,只要求i中有多少个j,即i/j,l+=i/j,最后再把i剩下的赋值给i 若i<j,只要求j中有多少个i,即j/i,r+=j/i,最后再把j剩下的赋值给j */ if(i>j){ l+=i/j; i-=i/j*j; //若i是j的倍数,即当j=1时,l要减去1,退出循环 //也可以上面l+=(i-1)/j,这样就不用讨论i=0的情况了。 if(i==0){ l--; break; } } else{ r+=j/i; j-=j/i*i; //若j是i的倍数,即当i=1时,r要减去1,退出循环 //也可以上面r+=(j-1)/i,这样就不用讨论j=0的情况了。 if(j==0){ r--; break; } } } printf("Scenario #%d: ",w); printf("%d %d ",l,r); puts(""); } return 0; }