Yes, there is a way. Consider a polynomial
(X + a[0]) * (X + a[1]) * ... * (X + a[n-1])
Its coefficients are simply the sums of k -products, its degree is n , so you can calculate the sum of all k -products for all k simultaneously in the O (n ^ 2) steps.
After steps s coefficient at X sk is the sum of k -products of the first elements of s . k products of the first elements s+1 are divided into two classes: those that are associated with the element (s+1) st - are of the form a[s]*((k-1) -product of the first elements s ) - and those not related to this, are the k products of the first elements of s .
The code is such that result[i] is the coefficient at X i (the sum of (ni) -products):
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; }
If you only need the sum of k -products for one k , you can stop the calculation with index nk by specifying the O (n * (nk)) algorithm - this is good if k >= n/2 . To get the O (n * k) algorithm for k <= n/2 , you need to organize the array of coefficients on the contrary, so result[k] is the coefficient at X nk (and stop calculating at index k if you want to get only one amount):
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; }
Daniel Fischer
source share