I will walk through two solutions that I proposed. Both of these solutions avoid any explicit looping. Mostly in R, if it is easy to avoid a loop, you probably should. First, let's get some example data.
set.seed(2017)
p = sample(5)
q = sample(5)
p
[1] 5 3 2 1 4
q
[1] 4 1 2 5 3
Here p and q are randomly generated. The set.seed part is so that we both get the same "random" numbers.
Solution 1 - matrix multiplication
p %*% t(q)
[,1] [,2] [,3] [,4] [,5]
[1,] 20 5 10 25 15
[2,] 12 3 6 15 9
[3,] 8 2 4 10 6
[4,] 4 1 2 5 3
[5,] 16 4 8 20 12
%*% is the way to specify matrix multiplication in R.
p %*% t(q) multiplies the 5x1 matrix p by the 1x5 matrix t(q), the transpose of q, resulting in the 5x5 matrix with the desired answer.
Solution 2 - outer
outer(p,q, `*`)
[,1] [,2] [,3] [,4] [,5]
[1,] 20 5 10 25 15
[2,] 12 3 6 15 9
[3,] 8 2 4 10 6
[4,] 4 1 2 5 3
[5,] 16 4 8 20 12
The function outer in r, creates the "outer product" of two vectors - that is, it takes all combinations of an element of p and an element of q and combines them using the function that you supplied, in this case *, exactly the calculation that you are asking for. Actually, this could have been written more succinctly as outer(p,q) because the default function to use to combine p & q is *.
p %*% t(q)orouter(p,q, `*`)seem like better solutions.