В связи со значительным прогрессом в программировании вычисления количества разбиений (partitions) целого числа
10. Сколько существует способов разложить
одинаковых шаров в
одинаковых урн?
Код:
N10(n,k)=#partitions(n,,[1,k])
Этот способ лаконичный, но для больших аргументов медленный или невыполнимый - т.к. создаётся массив разбиений, объем которого может быть очень велик, после чего подсчитывается количество элементов массива.
Следующие две функции подсчитывают требуемое количество намного быстрее и потребляют меньше памяти.
10.1 "Прямой" подсчет по рекуррентной формуле
с запоминанием промежуточных результатов. Для больших аргументов переполняется массив в котором запоминаются предыдущие вычисления.
(Оффтоп)
Код:
N10_1(n,k)=
{
local(M = Map());
my(memo_p = (N,K)-> my(res);
if(N==0 && K==0,
return(1));
if(K<1,
return(0));
if(mapisdefined(M,[N,K],&res),
return(res));
if(K>=N,
res=numbpart(N);
mapput(M,[N,K],res);
return(res));
res=self()(N,K-1)+self()(N-K,K);
mapput(M,[N,K],res);
return(res));
memo_p(n,k);
}
10.2. "Хитрый" подсчет созданием матрицы размером
[k+1] x [k] и последовательным вычислением, требует примерно n x k вычислений. Позаимствован в списке рассылки пользователей pari/gp у Karim Belabas (
http://pari.math.u-bordeaux.fr/archives ... 00015.html ) Промежуточная структура тоже может быть очень большой, но скорее ограничение тут по скорости работы:
(Оффтоп)
Код:
N10_2(n,k) =
{
my(k1 = k+1, kx = k1, a = 1, t = vector(k1, i, vector(k)));
t[k1][1] = 1;
for (i = 1, n-1,
my(ky = a);
t[a] = vector(k, j, if (!(ky--), ky = k1);
if (j == 1, t[ky][1]
, t[kx][j-1] + t[ky][j]));
kx = a; if (a++ > k1, a = 1));
vecsum(t[a-1]);
}
Сравнительная скорость вычислений:
(Оффтоп)
? N10(70,30)
time = 203 ms.
%1 = 3910071
? N10_1(70,30)
time = 31 ms.
%2 = 3910071
? N10_2(70,30)
%3 = 3910071
? ##
*** last result computed in 0 ms.
Берем значения побольше. Первый метод -- не хватает памяти.
Два других:
? N10_1(1000,300)
time = 2,637 ms.
%4 = 24060233693068843871790330541103
? N10_2(1000,300)
time = 172 ms.
%5 = 24060233693068843871790330541103
? N10_2(10000,3000)
time = 28,407 ms.
%6 = 36167251325636291851786878829976856243927867494801874150751474019863050338273687745917678081066889663513003
11. Сколько существует способов разложить
одинаковых шаров в
одинаковых урн так, чтобы в каждой урне было не более одного шара (при условии
)?
Код:
N11(n,k)=if(k>=n,return(1),return(0))
12. Сколько существует способов разложить n одинаковых шаров в k одинаковых урн так, чтобы в каждой урне было не менее одного шара (при условии
)?
Код:
N12(n,k)=#partitions(n,,[k,k])
Замечания те же что и для задачи 10, так что только привожу "быстрый" код для решения:
(Оффтоп)
Код:
N12_2(n,k)=
{
my(k1 = k+1, kx = k1, a = 1, t = vector(k1, i, vector(k)));
t[k1][1] = 1;
for (i = 1, n-k-1,
my(ky = a);
t[a] = vector(k, j, if (!(ky--), ky = k1);
if (j == 1, t[ky][1]
, t[kx][j-1] + t[ky][j]));
kx = a; if (a++ > k1, a = 1));
vecsum(t[a-1]);
}