Program to generate an array having convolution of two given arrays

04 Aug, 2021
Given two arrays A[] and B[] consisting of N and M integers respectively, the task is to construct a convolution array C[] of size (N + M – 1). 
The convolution of 2 arrays is defined as C[i + j] = ∑(a[i] * b[j]) for every i and j. 
Note: If the value for any index becomes very large, then print it to modulo 998244353.
Examples:
Input: A[] = {1, 2, 3, 4}, B[] = {5, 6, 7, 8, 9}Output: {5, 16, 34, 60, 70, 70, 59, 36}Explanation:Size of array, C[] = N + M – 1 = 8.C[0] = A[0] * B[0] = 1 * 5 = 5C[1] = A[0] * B[1] + A[1] * B[0] = 1 * 6 + 2 * 5 = 16C[2] = A[0] * B[2] + A[1] * B[1] + A[2] * B[0] = 1 * 7 + 2 * 6 + 3 * 5 = 34Similarly, C[3] = 60, C[4] = 70, C[5] = 70, C[6] = 59, C[7] = 36.
Input: A[] = {10000000}, B[] = {10000000}Output: {871938225}Explanation:Size of array, C[] = N + M – 1 = 1.C[0] = A[0] * B[0] = (10000000 * 10000000) % 998244353 = 871938225
Naive Approach: In the convolution array, each term C[i + j] = (a[i] * b[j]) % 998244353. Therefore, the simplest approach is to iterate over both the arrays A[] and B[] using two nested loops to find the resulting convoluted array C[].
Below is the implementation of the above approach:
C++
Java
Python3
C#
Javascript
// C++ program for the above approach#include <bits/stdc++.h>using namespace std;constexpr int MOD = 998244353; // Function to generate a convolution// array of two given arraysvoid findConvolution(const vector<int>& a,                     const vector<int>& b){    // Stores the size of arrays    int n = a.size(), m = b.size();     // Stores the final array    vector<long long> c(n + m - 1);     // Traverse the two given arrays    for (int i = 0; i < n; ++i) {        for (int j = 0; j < m; ++j) {                         // Update the convolution array            c[i + j] += 1LL*(a[i] * b[j]) % MOD;        }    }     // Print the convolution array c[]    for (int k = 0; k < c.size(); ++k) {        c[k] %= MOD;        cout << c[k] << " ";    }} // Driver Codeint main(){    vector<int> A = { 1, 2, 3, 4 };    vector<int> B = { 5, 6, 7, 8, 9 };       findConvolution(A, B);     return 0;}
// Java program for the above approachimport java.util.*; class GFG{ static int MOD = 998244353; // Function to generate a convolution// array of two given arraysstatic void findConvolution(int[] a,                            int[] b){         // Stores the size of arrays    int n = a.length, m = b.length;     // Stores the final array    int[] c = new int[(n + m - 1)];     // Traverse the two given arrays    for(int i = 0; i < n; ++i)    {        for(int j = 0; j < m; ++j)        {                         // Update the convolution array            c[i + j] += (a[i] * b[j]) % MOD;        }    }     // Print the convolution array c[]    for(int k = 0; k < c.length; ++k)    {        c[k] %= MOD;        System.out.print(c[k] + " ");    }} // Driver Codepublic static void main(String args[]){    int[] A = { 1, 2, 3, 4 };    int[] B = { 5, 6, 7, 8, 9 };       findConvolution(A, B);}} // This code is contributed by souravghosh0416
# Python3 program for the above approachMOD = 998244353 # Function to generate a convolution# array of two given arraysdef findConvolution(a, b):         global MOD         # Stores the size of arrays    n, m = len(a), len(b)     # Stores the final array    c = [0] * (n + m - 1)     # Traverse the two given arrays    for i in range(n):        for j in range(m):                         # Update the convolution array            c[i + j] += (a[i] * b[j]) % MOD     # Print the convolution array c[]    for k in range(len(c)):        c[k] %= MOD        print(c[k], end = " ") # Driver Codeif __name__ == '__main__':         A = [1, 2, 3, 4]    B = [5, 6, 7, 8, 9]         findConvolution(A, B) # This code is contributed by mohit kumar 29
// C# program for the above approachusing System; class GFG{ static int MOD = 998244353; // Function to generate a convolution// array of two given arraysstatic void findConvolution(int[] a,                    int[] b){       // Stores the size of arrays    int n = a.Length, m = b.Length;     // Stores the final array    int[] c = new int[(n + m - 1)];     // Traverse the two given arrays    for (int i = 0; i < n; ++i) {        for (int j = 0; j < m; ++j) {                         // Update the convolution array            c[i + j] += (a[i] * b[j]) % MOD;        }    }     // Print the convolution array c[]    for (int k = 0; k < c.Length; ++k) {        c[k] %= MOD;        Console.Write(c[k] + " ");    }} // Driver Codepublic static void Main(String[] args){    int[] A = { 1, 2, 3, 4 };    int[] B = { 5, 6, 7, 8, 9 };       findConvolution(A, B);}} // This code is contributed by code_hunt.
<script> // Javascript program for the above approach let MOD = 998244353;  // Function to generate a convolution// array of two given arraysfunction findConvolution(a, b){          // Stores the size of arrays    let n = a.length, m = b.length;      // Stores the final array    let c = [];    for(let i = 0; i < n + m - 1; ++i)    {        c[i] = 0;    }      // Traverse the two given arrays    for(let i = 0; i < n; ++i)    {        for(let j = 0; j < m; ++j)        {                          // Update the convolution array            c[i + j] += (a[i] * b[j]) % MOD;        }    }      // Print the convolution array c[]    for(let k = 0; k < c.length; ++k)    {        c[k] %= MOD;        document.write(c[k] + " ");    }} // Driver Code     let A = [ 1, 2, 3, 4 ];    let B = [ 5, 6, 7, 8, 9 ];        findConvolution(A, B); </script>
5 16 34 60 70 70 59 36
 
Time Complexity: O(N*M)Auxiliary Space: O(N+M)
Efficient Approach: To optimize the above approach, the idea is to use the Number-Theoretic Transform (NTT) which is similar to Fast Fourier transform (FFT) for polynomial multiplication, which can work under modulo operations. The problem can be solved by using the same concept of iterative FFT to perform NTT on the given arrays as the same properties hold for the Nth roots of unity in modular arithmetic. 
Below is the implementation of the above approach:
C++
// C++ program for the above approach#include <bits/stdc++.h>using namespace std; #define ll long long const ll mod = 998244353, maxn = 3e6;ll a[maxn], b[maxn]; // Iterative FFT function to compute// the DFT of given coefficient vectorvoid fft(ll w0, ll n, ll* a){    // Do bit reversal of the given array    for (ll i = 0, j = 0; i < n; i++) {         // Swap a[i] and a[j]        if (i < j)            swap(a[i], a[j]);         // Right Shift N by 1        ll bit = n >> 1;         for (; j & bit; bit >>= 1)            j ^= bit;        j ^= bit;    }     // Perform the iterative FFT    for (ll len = 2; len <= n; len <<= 1) {         ll wlen = w0;        for (ll aux = n; aux > len; aux >>= 1) {            wlen = wlen * wlen % mod;        }         for (ll bat = 0; bat + len <= n; bat += len) {             for (ll i = bat, w = 1; i < bat + len / 2;                 i++, w = w * wlen % mod) {                 ll u = a[i], v = w * a[i + len / 2] % mod;                 // Update the value of a[i]                a[i] = (u + v) % mod,                 // Update the value                // of a[i + len/2]                    a[i + len / 2]                    = ((u - v) % mod + mod) % mod;            }        }    }} // Function to find (a ^ x) % modll binpow(ll a, ll x){    // Stores the result of a ^ x    ll ans = 1;     // Iterate over the value of x    for (; x; x /= 2, a = a * a % mod) {         // If x is odd        if (x & 1)            ans = ans * a % mod;    }     // Return the resultant value    return ans;} // Function to find the// inverse of a % modll inv(ll a) { return binpow(a, mod - 2); } // Function to find the// convolution of two arraysvoid findConvolution(ll a[], ll b[], ll n, ll m){    // Stores the first power of 2    // greater than or equal to n + m    ll _n = 1ll << 64 - __builtin_clzll(n + m);     // Stores the primitive root    ll w = 15311432;    for (ll aux = 1 << 23; aux > _n; aux >>= 1)        w = w * w % mod;     // Convert arrays a[] and    // b[] to point value form    fft(w, _n, a);    fft(w, _n, b);     // Perform multiplication    for (ll i = 0; i < _n; i++)        a[i] = a[i] * b[i] % mod;     // Perform inverse fft to    // recover final array    fft(inv(w), _n, a);    for (ll i = 0; i < _n; i++)        a[i] = a[i] * inv(_n) % mod;     // Print the convolution    for (ll i = 0; i < n + m - 1; i++)        cout << a[i] << " ";} // Driver Codeint main(){    // Given size of the arrays    ll N = 4, M = 5;     // Fill the arrays    for (ll i = 0; i < N; i++)        a[i] = i + 1;     for (ll i = 0; i < M; i++)        b[i] = 5 + i;     findConvolution(a, b, N, M);     return 0;}
5 16 34 60 70 70 59 36
 
Time Complexity: O(N*log(N))Auxiliary Space: O(N + M)
 
mohit kumar 29
code_hunt
souravghosh0416
avijitmondal1998
gabaa406
Technical Scripter 2020
Arrays
Mathematical
Technical Scripter
Arrays
Mathematical
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.
Maximum and minimum of an array using minimum number of comparisons
Top 50 Array Coding Problems for Interviews
Multidimensional Arrays in Java
Stack Data Structure (Introduction and Program)
Linear Search
Set in C++ Standard Template Library (STL)
Write a program to print all permutations of a given string
C++ Data Types
Merge two sorted arrays
Coin Change | DP-7