Да, есть способ.Рассмотрим полином
(X + a[0]) * (X + a[1]) * ... * (X + a[n-1])
. Его коэффициенты - это просто суммы k
-произведений, его степень равна n
, поэтому вы можете вычислить сумму всех k
-произведений для всех k
одновременно в O (n ^ 2) шагов.
После s
шагов, коэффициент X sk является суммой k
-произведений первого s
элементы массива.k
-продукты первых s+1
элементов делятся на два класса, включая (s+1)
st - они имеют форму a[s]*((k-1)
-продукта первых s
элементов)- и те, кто его не задействует - это k
-продукты первых s
элементов.
Код такой, что result[i]
является коэффициентом X i (суммаиз (n-i)
-продукции):
int *k_products_1(int *a, int n){
int *new, *old = calloc((n+1)*sizeof(int));
int d, i;
old[0] = 1;
for(d = 1; d <= n; ++d){
new = calloc((n+1)*sizeof(int));
new[0] = a[d-1]*old[0];
for(i = 1; i <= d; ++i){
new[i] = old[i-1] + a[d-1]*old[i];
}
free(old);
old = new;
}
return old;
}
Если вы хотите получить сумму k
-произведений только для одного k
, вы можете остановить вычисление по индексу n-k
, даваяАлгоритм O (n * (nk)) - это хорошо, если k >= n/2
.Чтобы получить алгоритм O (n * k) для k <= n/2
, необходимо организовать массив коэффициентов наоборот, чтобы result[k]
был коэффициентом X nk (и остановить вычисление прииндекс k
, если вы хотите только одну сумму):
int *k_products_2(int *a, int n){
int *new, *old = calloc((n+1)*sizeof(int));
int d, i;
old[0] = 1;
for(d = 1; d <= n; ++d){
new = calloc((n+1)*sizeof(int));
new[0] = 1;
for(i = 1; i <= d; ++i){
new[i] = old[i] + a[d-1]*old[i-1];
}
free(old);
old = new;
}
return old;
}