Problem Statement – https://dmoj.ca/problem/ccc15j5
This problem is a multi-way choice DP problem, because we can distribute the pie in a lot of way. At first we will solve a simpler version of this, that is the number of ways we can distribute pie among people without any restriction.
Let f(n, k) denote the number of ways we can distribute ‘n’ slices to ‘k’ people, therefore recurrence will be f(n, k) = ∑ f(n-i, k-1) , here ‘n-i’ checks all the possible combination and since we distributed the slice, number of people will reduce to ‘k-1’.
Since mathematicians are a bit greedy at times. So, they always get at least as many of pieces of pie as the person in front of them.
In order to solve this, we add another parameter i.e, f(n, k, m) , where ‘m’ denotes the number of slice the last person took.
Now the recurrence will be f(n, k, m) = ∑ f(n-i, k-1, i) , and this time ‘i’ loop will be from ‘m’ to ‘n/k’. This is obvious.
Finally we memoize it to reduce the time complexity.
The Implementation is rather straight-forward
#include <bits/stdc++.h>
using namespace std;
int n, k;
int dp[255][255][255];
class fastio {
public:
fastio() {
ios_base::sync_with_stdio(false);
cout.tie(nullptr);
cin.tie(nullptr);
}
} __fastio;
int f(int n, int k, int m) {
if(dp[n][k][m] != -1) return dp[n][k][m];
if(k == 1 || k == n) return 1;
if(k > n) return 0;
else {
int ans = 0;
for(int i=m; i<=n/k; i++) {
ans += f(n - i, k - 1, i);
}
return dp[n][k][m] = ans;
}
}
void solve() {
cin >> n >> k;
memset(dp, -1, sizeof(dp));
cout << f(n, k, 1) << endl;
}
int main() {
__fastio;
solve();
return 0;
}