您的位置:首页 > 其它

UVA 10516 - Another Counting Problem(递推)

2013-11-20 20:35 1366 查看
Problem H

Another Counting Problem

Input: 
Standard Input
Output: Standard Output
Tree is an important data structure in Computer Science. Of all trees we work with, Binary Tree is probably the most popular one. A Binary Tree is called Strictly Binary Tree if every nonleaf node in a binary tree has nonempty left and
right subtrees. Let us define a Strictly Binary Tree of depth d, as a Strictly Binary Tree that has at least one root to leaf path of length d, and no root to leaf path in that tree is longer than d.
So let us use a similar reasoning to define a generalized structure.

A n-ary Tree is called Strictly n-ary Tree if every nonleaf node in a n-ary tree has n children each. a Strictly n-ary Tree of depth d, then can be defined as a Strictly n-ary Tree that has at least one root
to leaf path of length d, and no root to leaf path in that tree is longer than d.

Given the value of n and depth d, your task is to find the number of different strictly n-ary trees of depth d.

The figure below shows the 3 different strictly binary trees of depth 2.



Input

Input consists of several test cases. Each test case consists of two integers n (0 < n <= 32), d (0 <= d <= 16). Input is terminated a test case where n=0 and d=0, you must not process this test case.

 

Output

For each test case, print three integers, n, d and the number of different strictly n-ary trees of level d, in a single line. There will be a single space in between two integers of a line. You can assume that you would not be asked about cases where
you had to consider trees that may have more than 210 nodes in a level of the tree. You may also find it useful to know that the answer for each test case will always fit in a 200 digit integer.


 

Sample Input                               Output for Sample Input

2 0

2 1

2 2

2 3

3 5

0 0

2 0 1

2 1 1

2 2 3

2 3 21

3 5 58871587162270592645034001

 

 

题意:n叉高度为d的严格二叉树有几种

思路:递推。dp[i]表示高度不超过i的总数。那么对于n叉树而言,每个子树都有dp[i - 1]种,那么一共就有dp[i - 1] ^ n种,在加上高度为1的一种,dp[i] = dp[i - 1]^n + 1;本来打表的,结果一直跑不出来。后来才发现题目说输出不会超过200位,而如果n <= 32 d <= 16,是有可能位数非常大的!。

代码:

#include <stdio.h>
#include <string.h>
#include <math.h>

#define max(a,b) (a)>(b)?(a):(b)
#define min(a,b) (a)<(b)?(a):(b)

const int MAXSIZE = 1005;

struct bign {
int s[MAXSIZE];
bign () {memset(s, 0, sizeof(s));}
bign (int number) {*this = number;}
bign (const char* number) {*this = number;}

void put();
bign mul(int d);
void del();

bign operator = (char *num);
bign operator = (int num);

bool operator < (const bign& b) const;
bool operator > (const bign& b) const { return b < *this; }
bool operator <= (const bign& b) const { return !(b < *this); }
bool operator >= (const bign& b) const { return !(*this < b); }
bool operator != (const bign& b) const { return b < *this || *this < b;}
bool operator == (const bign& b) const { return !(b != *this); }

bign operator + (const bign& c);
bign operator * (const bign& c);
bign operator - (const bign& c);
int operator / (const bign& c);
bign operator / (int k);
bign operator % (const bign &c);
int operator % (int k);
void operator ++ ();
bool operator -- ();
};

bign bign::operator = (char *num) {
s[0] = strlen(num);
for (int i = 1; i <= s[0]; i++)
s[i] = num[s[0] - i] - '0';
return *this;
}

bign bign::operator = (int num) {
char str[MAXSIZE];
sprintf(str, "%d", num);
return *this = str;
}

bool bign::operator < (const bign& b) const {
if (s[0] != b.s[0])
return s[0] < b.s[0];
for (int i = s[0]; i; i--)
if (s[i] != b.s[i])
return s[i] < b.s[i];
return false;
}

bign bign::operator + (const bign& c) {
int sum = 0;
bign ans;
ans.s[0] = max(s[0], c.s[0]);

for (int i = 1; i <= ans.s[0]; i++) {
if (i <= s[0]) sum += s[i];
if (i <= c.s[0]) sum += c.s[i];
ans.s[i] = sum % 10;
sum /= 10;
}
return ans;
}

bign bign::operator * (const bign& c) {
bign ans;
ans.s[0] = 0;

for (int i = 1; i <= c.s[0]; i++){
int g = 0;

for (int j = 1; j <= s[0]; j++){
int x = s[j] * c.s[i] + g + ans.s[i + j - 1];
ans.s[i + j - 1] = x % 10;
g = x / 10;
}
int t = i + s[0] - 1;

while (g){
++t;
g += ans.s[t];
ans.s[t] = g % 10;
g = g / 10;
}

ans.s[0] = max(ans.s[0], t);
}
ans.del();
return ans;
}

bign bign::operator - (const bign& c) {
bign ans = *this;
for (int i = 1; i <= c.s[0]; i++) {
if (ans.s[i] < c.s[i]) {
ans.s[i] += 10;
ans.s[i + 1]--;;
}
ans.s[i] -= c.s[i];
}

for (int i = 1; i <= ans.s[0]; i++) {
if (ans.s[i] < 0) {
ans.s[i] += 10;
ans.s[i + 1]--;
}
}

ans.del();
return ans;
}

int bign::operator / (const bign& c) {
int ans = 0;
bign d = *this;
while (d >= c) {
d = d - c;
ans++;
}
return ans;
}

bign bign::operator / (int k) {
bign ans;
ans.s[0] = s[0];
int num = 0;
for (int i = s[0]; i; i--) {
num = num * 10 + s[i];
ans.s[i] = num / k;
num = num % k;
}
ans.del();
return ans;
}

int bign:: operator % (int k){
int sum = 0;
for (int i = s[0]; i; i--){
sum = sum * 10 + s[i];
sum = sum % k;
}
return sum;
}

bign bign::operator % (const bign &c) {
bign now = *this;
while (now >= c) {
now = now - c;
now.del();
}
return now;
}

void bign::operator ++ () {
s[1]++;
for (int i = 1; s[i] == 10; i++) {
s[i] = 0;
s[i + 1]++;
s[0] = max(s[0], i + 1);
}
}

bool bign::operator -- () {
del();
if (s[0] == 1 && s[1] == 0) return false;

int i;
for (i = 1; s[i] == 0; i++)
s[i] = 9;
s[i]--;
del();
return true;
}

void bign::put() {
if (s[0] == 0)
printf("0");
else
for (int i = s[0]; i; i--)
printf("%d", s[i]);
}

bign bign::mul(int d) {
s[0] += d;
for (int i = s[0]; i > d; i--)
s[i] = s[i - d];
for (int i = d; i; i--)
s[i] = 0;
return *this;
}

void bign::del() {
while (s[s[0]] == 0) {
s[0]--;
if (s[0] == 0) break;
}
}

int n, m;
bign dp[17], one = 1;

void solve() {
dp[0] = 1;
for (int j = 1; j <= m; j ++) {
dp[j] = 1;
for (int k = 0; k < n; k ++) {
dp[j] = dp[j] * dp[j - 1];
}
dp[j] = dp[j] + one;
}
(dp[m] - dp[m - 1]).put();
printf("\n");
}

int main() {
while (~scanf("%d%d", &n, &m) && n) {
printf("%d %d ", n, m);
if (m == 0) printf("1\n");
else solve();
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: