Что вам нужно, это динамическое программирование.Вам нужно запомнить значения функции f для тех аргументов, для которых она уже была рассчитана.Также это может быть реализовано без рекурсии следующим образом:
int f(int n,int a,int x)
{
int q[1000][50]; // to simplify and not use dynamic allocation assume that a < 50 and n < 1000
q[0][0] = 1;
for (int i = 1; i < 1000; ++i)
q[i][0] = 0;
for (int i = 1; i <= a; ++i)
{
for (int j = 0; j <= n; j++)
{
int t = 0;
for (int l = 0; l <= j && l <= x; ++l)
t += q[j - l][i-1];
q[j][i] = t;
}
}
return q[n][a];
}
Это всего лишь простая демонстрация техники.Его можно оптимизировать еще раз, вы можете предварительно рассчитать t-сумму и исключить цикл для l.И вам не нужно хранить всю таблицу q, вам нужно всего два слоя, это уменьшит использование памяти.Таким образом, результат будет выглядеть следующим образом:
int f(int n,int a,int x)
{
int q[1000][2]; // to simplify and not use dynamic allocation assume n < 1000
q[0][0] = 1;
for (int i = 1; i < 1000; ++i)
q[i][0] = 0;
int current = 1;
for (int i = 1; i <= a; ++i)
{
int t = 0;
for (int j = 0; j <= n; j++)
{
t += q[j][1 - current];
if (j > x)
t -= q[j - x - 1][1 - current];
q[j][current] = t;
}
current = 1 - current;
}
return q[n][1 - current];
}
Итак, в конце концов, потребуется O (a * n) время для вычисления.
PS: обратите внимание, что ответом может быть огромное число, которое может быть переполнено любым целым типом.