// _Alejandro B. Galván_, Dec 29 2023 (C++) #include #include #include #include using namespace std; using vi = vector; // This function runs through all (m, d) such that there exists tau with chi(tau) = (m,d,w[0 : i - 1]), computes the size n = |tau| // and registers it in counter[n]. void count_partitions(vi& counter, const int N, const int i, const bool add_one, int nmin) { nmin += i + 1; // nmin := minimum size of a partition with wrd(tau) = w[0 : i - 1]. if (N < nmin) return; if (nmin == (i + 1)*(i + 2)/2) { ++counter[nmin]; // We only count the staircase once because it is its own conjugate. } else counter[nmin] += 2; // We go through all the other possible (m, d) such that there exists tau with chi(tau) = (m,d,w[0 : i - 1]) and count them. if (add_one and nmin + i + 1 <= N) counter[nmin + i + 1] += 2; int d = 2; int size = nmin + i*(i + 1)/2; while (size <= N) { for (int m = 1; m <= d + add_one and size + (m - 1)*(i + 1) <= N; ++m) counter[size + (m - 1)*(i + 1)] += 2; ++d; size += i*(i + 1)/2; } return; } // This function performs a dfs algorithm to search through the tree of balanced words. // i := number of entries of w that are part of the current word; zeros == true if the word has some entry equal to zero. void count_words(vi& counter, vi& w, const vi restrictions, const int N, const int maxn, const int i, bool zeros, int nmin) { vi restrict_copy = restrictions; // restrictions[x] == 1 iff sum_{j=i-x}^{i-1}w[j] = min_k(sum_{j=k}^{k + x - 1}w[j]) + 1. bool add_one = true; for (int x = 2; x <= i; ++x) { if (not w[i - x]) { if (restrict_copy[x] == 1) add_one = false; else restrict_copy[x] = 1; } } // If the word has some zero entry, we count partitions with wrd(tau) = w[0 : i-1]. if (zeros) count_partitions(counter, N, i, add_one, nmin); if (i == maxn) { return; } if (add_one) { // add_one == true iff w[0],w[1],...,w[i-1],1 is a balanced word. w[i] = 1; count_words(counter, w, restrict_copy, N, maxn, i + 1, zeros, nmin + 2*(i + 1)); } restrict_copy = restrictions; // restrictions[x] = 0 iff sum_{j=i-x}^{i-1}w[j] = max_k(sum_{j=k}^{k + x - 1}w[j]) - 1. bool add_zero = true; for (int x = 2; x <= i; ++x) { if (w[i - x]) { if (restrict_copy[x] == 0) add_zero = false; else restrict_copy[x] = 0; } } if (add_zero) { // add_zero == true iff w[0],w[1],...,w[i-1],0 is a balanced word. w[i] = 0; if (not zeros) zeros = true; // all words without zeros are visited before the first zero is added. count_words(counter, w, restrict_copy, N, maxn, i + 1, zeros, nmin + i + 1); } return; } int main() { int N; // N := maximum n for which we want to compute |Delta(n)|. cin >> N; vi counter(N + 1); // counter[n] := # of partitions of size n found. counter[0] = 1; counter[1] = 1; for (int x = 2; x <= N; ++x) counter[x] = 2; // this accounts for partitions with 1 part and their conjugates. int maxn = sqrt(2*N)/1 - 1; // maxn := maximum size of the balanced word. vi w(maxn); // w := balanced word. vi restrictions(maxn + 1); // this vector will be used to know if a 0 or a 1 can be appended to the word. for (int x = 0; x < maxn; ++x) restrictions[x] = -2; count_words(counter, w, restrictions, N, maxn, 0, false, 0); ofstream MyFile("b352882.txt"); // the output is written in a text file named "b352882.txt". for (int x = 0; x <= N; ++x) MyFile << x << " " << counter[x] << endl; MyFile << endl; MyFile.close(); }