解题报告 之 SOJ1678 Mountains

来源:互联网 发布:可以听pdf的软件 编辑:程序博客网 时间:2024/05/16 02:01

解题报告 之 SOJ1678 Mountains


Description

A mountain consists of one or more hills, each of which consists of upwards, which we denote with `/', and downwards, which we denote with '\'. We call upwards and downwards together as wards. Let /n be an upward of length n, and in the same way, let \n be a downward of length n. For example, the following upward is /2:

 //

and the following downward is \3:

\ \  \

The set of all hills is given in the following:

Hills =def { /n\n | n is a natural number }

Now it comes to the definition of a mountain(in BNF):

Mountain ::= Hill | Mountain Mountain

That's to say, a hill is a mountain, and if M and N are mountains, then the concatenation of M and N is also a mountain.

For example,

     /\/\/\/  \

is a mountain with 3 hills.

We define the width of a mountain as the number of upwards and downwards. We define the height of a mountain as the maximum length of upwards(or equivalently downwards).

We can give each mountain a unique number, called index, such that the following conditions are met:

  1. index begins with 1
  2. the index of a mountain with larger width is larger
  3. if two mountains have the same width, then the index of the mountain whose leftmost different ward with the other mountain is an upward is larger

For example, portion of the mountains and their indices are:

                 /\                    /\                   /\         /\/\     /\/\     /  \     /\/\/\     /\/  \     ...     /\/\/  \     /\/  \/\     ...1       2        3         4          5                   9            10

In this problem, you are print the mountain from the given index.

Input

The input contains several lines, each of which contains an integer N<2^32. The last line contains 0, which you should not proceed.

Output

For each N, your program should print the mountain. For simplicity, you needn't make the mountain climbing. You can imagine that the mountain finally printed is the one after being flattened. For example, for N=9, your program should simply print:

/\/\//\\

.

Each mountain should be printed in a single line.

Sample Input

690

Sample Output

//\\/\/\/\//\\ 

Problem Source: siyee


题目大意:每条山脉都由一些山头构成,且每座山脉有一个排名,如果一座山宽度比较小或者宽度一样大但字典序小(即山包的宽度字典序),那么它的排名就更靠前。问你排名第n的山脉长什么样子?

分析:首先很明显的是序列和是从1,2,3……n这么排的,设f(n)为序列和为n的排列方法数,那么很容易推出:
f(n) = f(n-1) + f(n-2) + …… + f(2) + f(1) + f(0)                with f(0) = f(1) = 0
怎么理解呢?对于f(n),我们先设在最左边放宽度为1的山包(注意是山包不是山脉),则右边还剩n-1个可放,方法数为f(n-1);然后再假设在最左边放一个宽度为2的山包,则方法数为f(n-2),依次类推……最后的加f(0)是直接放一个宽度为n的山包。这样想绝不会有重复,因为最左边的第一个山包形状各不相同;也不会漏解。

那么我们可以发现f(n)=2^(n-1)。然后我们再通过二分来确定目标排名的位置,期间顺便填上数。digit表示当前位的数字,loc表示排名在本层的位置,如果loc<=mid,说明在当前左边,那么就填上digit并digit=1(下一个数又从1开始填);否则说明再右边,digit+1。
最后在输出结果即可。

上代码:
#include<iostream>#include<algorithm>#include<string>#include<cmath>using namespace std;int num[50];long long q_pow( long long a, long long b )  //快速幂 计算a^b,直接用pow感觉也行{long long ans = 1;while(b){if(b & 1){ans *= a;}b /= 2;a *= a;}return ans;}int main(){long long n;while(cin >> n&&n){int w = log2( n ) + 1; //计算宽度long long loc = n - (q_pow( 2, w - 1 ) - 1);//计算目标排名在本层的相对位置int h = 1;int cnt = 1;int digit = 1;long long l = 1, r = q_pow( 2, w - 1 );while(l < r)//二分找位置填数{long long mid = (l + r) / 2;if(loc <= mid)//很容易发现前一半的解都是以digit为当前位的{num[cnt++] = digit;digit = 1;r = mid;}else          //后一半的解的最小的数位为digit+1,后面接着二分{digit++;l = mid + 1;}}num[cnt] = digit;for(int j = 1; j <= cnt; j++){cout << string( num[j], '/' ) << string( num[j], '\\' );}cout << endl;}return 0;}

另外有一篇SOJ 2714是这个题的升级版,输出比较复杂,有兴趣可以看看。
0 0