【hiho一下第77周】递归-减而治之 (MS面试题:Koch Snowflake)

本题是一道微软面试题,看起来复杂,解出来会发现其实是一个很简单的递归问题,但是这道题的递归思路是很值得我们反复推敲的。

原题为hihocoder第77周的题目。


描述

【hiho一下第77周】递归-减而治之 (MS面试题:Koch Snowflake)

Koch Snowflake is one of the most famous factal. It is built by starting with an equilateral triangle, removing the inner third of each side, building another equilateral triangle at the location where the side was removed, and then repeating the process indefinitely.

Let Kn be the Koch Snowflake after n-th iteration. It is obvious that the number of sides of Kn, Nn, is 3*4n. Let's number the sides clockwisely from the top of Koch Snowflake.

Let si,n be the i-th side of Kn. The generation of si,n is defined as the smallest m satifying si,n is a part of the sides of Km. For example, in the above picture, the yellow sides are of generation 0; the blue sides are of generation 1; the red sides are of generation 2.

Given a side si,n, your task is to calculate its generation.

输入

The input contains several test cases.

The first line contains T(T <= 1000), the number of the test cases.

The following T lines each contain two numbers, i(1 <= i <= 10^9) and n(0 <= n <= 1000). Your task is to calculate the generation of side si,n.

输出

For each test case output the generation of the side.

样例输入
5
1 0
1 1
2 1
10 2
16 3
样例输出
0
0
1
2
0

题目大意:

  给定一个三角形,每经过一次扩展,每一条边变成4条小边。告诉你扩展的次数n,以及边的编号i,求该条边是第几次扩展出现的边。

题目思路:

  这道题初看是令人有点头疼的数学问题,需要找数字之间的规律,如果单看每一次扩展,找规律就会显得非常复杂,要让解题过程简单化,就应该从一条边看起。

  我用hihocoder上题目分析的图片来解释会更加直观,例如第i条边经过扩展后:

  【hiho一下第77周】递归-减而治之 (MS面试题:Koch Snowflake)

  也就是说中间两条边是经过第n次扩展后得到的,而左右两边则不能够确定。

  左右两边经过规律的反推可以继续找这条件是否属于第n-1次扩展,否则继续减而治之。

  具体代码如下:

  

 //递归(减而治之)-单边分析
//第i条边经扩展后的四边编号
//i->4 * (i - 1) + 1, 4 * (i - 1) + 2, 4 * (i - 1) + 3, 4 * (i - 1) + 4
//Time:0Ms Memory:0K
#include<iostream>
#include<cstdio>
using namespace std; int cal(int side, int n)
{
if (n == )
return ;
if (side % == || side % == ) //如果边模4为2或3 则确定为n次扩展出的边
return n;
else //否则 减小一个规模continue
return cal((side + ) / , n - ); //降低的边数 经归纳可等价 (side + 3)/4
} int main()
{
int T;
scanf("%d", &T);
while (T--)
{
int side, n;
scanf("%d%d", &side, &n);
printf("%d\n", cal(side, n));
} return ;
}
上一篇:Solution: 最近公共祖先·一 [hiho一下 第十三周]


下一篇:C语言快速排序