I've been working on the USACO training problem Cow Pedigrees (see https://jvonk.github.io/usaco/2018/10/16/nocows.html for an explanation of the problem and a sample solution)
Basically, you have to count the number (mod 9901) of possibilities of unique binary trees with a number of nodes N and a height of K.
Here is the C++ code that I've tried so far. It outputs the correct answers for some smaller inputs like N = 5; K = 3 and N = 9; K = 4. However, once it got to the test case of N = 35 and K = 7, it outputs 7642 instead of the correct answer of 5024.
I cannot for the life of me figure out why that is, because my code all makes sense to me, and when I walk through the steps with smaller numbers it seems to be doing everything correctly and the same as if I did it manually. I think the issue is something to do with it double counting possibilities that should not be double counted (in the if else statement) but I can't figure out why that would be true.
I would really appreciate if someone could explain where my approach is going wrong and how I could correct it!! Thanks in advance.
#include <bits/stdc++.h>
using namespace std;
int main() {
// values
int N, K;
int possibilities[201][101]{};
// input
ifstream fin("nocows.in");
fin >> N >> K;
// solution
possibilities[1][1] = 1;
for (int k = 2; k <= K; k++){ // for every possible height
// 1 node is used for the "mother", the amount of the rest of the nodes will be between 2*(k - 1) and -2 * (1-2^(k-1))
for (int n = 2 * (k - 1); n <= 2 * (pow(2, k - 1) - 1) && n <= N; n += 2 ){
// one side will have n1 nodes - anywhere odd number from 1 to n; and a height of k - 1
for (int n1 = 1; n1 < n; n1 += 2){
// the other side will have any height k - 1 or less and the remaining nodes
for (int k1 = 1; k1 < k; k1++){
// if they are different numbers, they will be doubled because they are not interchangable so can work for both right and left
if (n1 != n - n1 || k1 != k - 1)
possibilities[n + 1][k] += (2 * possibilities[n1][k - 1] * possibilities[n - n1][k1]) % 9901;
else
possibilities[n + 1][k] += (possibilities[n1][k - 1] * possibilities[n - n1][k1]) % 9901;
possibilities[n + 1][k] %= 9901;
}
}
}
}
// output
ofstream fout("nocows.out");
fout << possibilities[N][K] % 9901 << '\n';
return 0;
}
edit: to clarify, this is a problem I was trying to solve to help me practice for competitive programming.
- Thus, because programs need to be written quickly, including the whole standard library and using the namespace is common practice to prevent the need to look up which specific parts of the standard library to use and makes typing the code faster, because you don't need to write out std::.
- This being practice for CP is also why a C-style array is used and not std::vector or std::array, because there are memory and time limitations and C-style arrays are generally faster to access and consume less memory.
- Also, because the number of possibilities could maybe become large enough to cause integer overflow, I am finding the remainder with respect to 9901 before adding it to array so that my numbers never get too large.