#include <iostream>
using namespace std;
int main() {
int tot=0;
// Each successive variable must be greater than the last to eliminate duplicates...
for (int a=1;a<=5;++a){ // sum(n,0,9,n+5) <= 100
for (int b=a+1;b<=7;++b){ // 1+sum(n,0,8,n+7) <= 100
for (int c=b+1;c<=8;++c){ // 1+2+sum(n,0,7,n+8) <= 100
for (int d=c+1;d<=10;++d){ // 1+2+3+sum(n,0,6,n+10) <= 100
for (int e=d+1;e<=12;++e){ // 1+2+3+4+sum(n,0,5,n+12) <= 100
for (int f=e+1;f<=15;++f){ // 1+2+3+4+5+sum(n,0,4,n+15) <= 100
for (int g=f+1;g<=18;++g){ // 1+2+3+4+5+6+sum(n,0,3,n+18) <= 100
for (int h=g+1;h<=23;++h){ // 1+2+3+4+5+6+7+sum(n,0,2,n+23) <= 100
int remain=100-(a+b+c+d+e+f+g+h);
// How many ways can the last two numbers sum to "remain"
int i;
if ((remain & 1)==1) { // remain is odd, i + (i+1) = remain
i=(remain - 1)/2;
}
else { // remain is even, i + (i+2) = remain
i=(remain - 2)/2;
}
i -= h;
if (i>0) tot+=i;
}
}
}
}
}
}
}
}
cout << tot << endl;
return 0;
}
#include <iostream>
using namespace std;
int getWays(int minGroupSize, int remainingGroups, int requiredTotal) {
if (remainingGroups == 2) {
// Special case
// Calculate the maximum possible size for the first of the two remaining groups
int max;
if ((requiredTotal & 1)==1) { // requiredTotal is odd, max + (max+1) = requiredTotal
max = (requiredTotal - 1)/2;
}
else { // requiredTotal is even, max + (max+2) = requiredTotal
max = (requiredTotal - 2)/2;
}
int ways = max - minGroupSize + 1;
return (ways>0) ? ways : 0;
}
else {
// Calculate the maximum possible size for this group, "max"
// We require...
// sum(n, 0, remainingGroups - 1, max + n) <= requiredTotal
// sum(n, 0, remainingGroups - 1, max) + sum(n, 0, remainingGroups - 1, n) <= requiredTotal
// remainingGroups*max + sum(n, 0, remainingGroups - 1, n) <= requiredTotal
// remainingGroups*max + remainingGroups*(remainingGroups - 1)/2 <= requiredTotal
// remainingGroups*(2*max + remainingGroups - 1)/2 <= requiredTotal
// 2*max + remainingGroups - 1 <= requiredTotal*2/remainingGroups
// 2*max <= requiredTotal*2/remainingGroups - remainingGroups + 1
int max = (requiredTotal*2/remainingGroups - remainingGroups + 1)/2;
int ways = 0;
for (int i = minGroupSize; i <= max; ++i) {
ways += getWays(i + 1, remainingGroups - 1, requiredTotal - i);
}
return ways;
}
}
/////////////////////////////////////////////////////////////
int main() {
cout << getWays(1, 10, 100) << endl; // the ways to partition 100 into 10 parts
cout << getWays(1, 11, 80) << endl; // the ways to partition 80 into 11 parts
return 0;
}
Extra credit: What is the benefit of doing something with a buffer instead of recursion?
1 2 3 4 5 6 7 8
P P . . . . . .
1 2 3 4 5 6 7 8
P P . . . . . . the number of ways to place 3 pegs on the remaining "."
= f(3, 3, 18-(1+2))
= f(3, 3, 15)
THE ABOVE IS EQUAL TO THE SUM OF THE FOLLOWING TWO AMOUNTS
1 2 3 4 5 6 7 8
P P P . . . . . the number of ways to place 2 "X" pegs on the remaining "."
= f(4, 2, 15-3)
PLUS
1 2 3 4 5 6 7 8
P P O . . . . . the number of ways to place 3 "X" pegs on the remaining "."
= f(4, 3, 15)
"O" means that there's no peg in that position
#include <iostream>
#include <map>
using namespace std;
map<int, map<int, map<int, long long> > > cache;
long long getWays(int h, int p, int t) {
int minSum=p*(2*h+p-1)/2;
if (t==minSum) return 1;
if (t<minSum) return 0;
if (p==1) return 1;
// Check the cache
auto& i=cache[h][p];
auto j=i.find(t);
if (j != i.end()) return j->second;
// use reduction formula
long long ways = getWays(h+1, p-1, t-h) + getWays(h+1, p, t);
// Insert into cache
i[t] = ways;
return ways;
}
/////////////////////////////////////////////////////////////
int main() {
cout << getWays(1, 10, 100) << endl; // the ways to partition 100 into 10 parts
cout << getWays(1, 10, 400) << endl;
return 0;
}
...recursion can quickly exhaust the available stack space (stack overflow), whereas a buffer can be much larger in size.