High Dimensional Prefix Sums
Hi, so everyone probably codes 2D prefix sums like this:
for (int x=1;x<=n;x++){
for (int y=1;y<=m;y++){
arr[x][y]+=arr[x-1][y]+arr[x][y-1]-arr[x-1][y-1];
}
}
and 3D prefix sums like this:
for (int x=1;x<=n;x++){
for (int y=1;y<=m;y++){
for (int z=1;z<=k;z++){
arr[x][y][z]+=arr[x-1][y][z]+arr[x][y-1][z]+arr[x][y][z-1]
-arr[x-1][y-1][z]-arr[x-1][y][z-1]-arr[x][y-1][z-1]
+arr[x-1][y-1][z-1];
}
}
}
This works for low dimensions, but when we go up into higher dimensions, the complexity explodes. Even though the above two codes looks like
Instead, we can do prefix sums in
2D:
for (int x=1;x<=n;x++){
for (int y=1;y<=m;y++){
arr[x][y]+=arr[x-1][y];
}
}
for (int x=1;x<=n;x++){
for (int y=1;y<=m;y++){
arr[x][y]+=arr[x][y-1];
}
}
The reason this works is because this does prefix sums on the columns first, and then on the rows.
As an illustration of this code we will explictly show the transformation of a
And the same code obviously works for 3D:
for (int x=1;x<=n;x++){
for (int y=1;y<=m;y++){
for (int z=1;z<=k;z++){
arr[x][y][z]+=arr[x-1][y][z];
}
}
}
for (int x=1;x<=n;x++){
for (int y=1;y<=m;y++){
for (int z=1;z<=k;z++){
arr[x][y][z]+=arr[x][y-1][z];
}
}
}
for (int x=1;x<=n;x++){
for (int y=1;y<=m;y++){
for (int z=1;z<=k;z++){
arr[x][y][z]+=arr[x][y][z-1];
}
}
}
Of course for low dimensions,
Sum Over Subsets
Problem statement: You are given an array
Firstly, if we write the code naively as follow:
int brr[1<<n];
for (int x=0;x<(1<<n);x++){
for (int y=x;;y=(y-1)&x){
brr[x]+=arr[y];
if (y==0) break;
}
}
This code is actually
The easier justification for it is we look at a certain bit for
Actually, if we write
And well, we already seen above how to do this in
For reference, this is the code:
for (int bit=0;bit<n;bit++){
for (int bm=0;bm<(1<<n);bm++) if (bm&(1<<bit)){
arr[bm]+=arr[bm^(1<<bit)];
}
}
Just for knowledge,
or-convolution of
Sum over Divisors
Problem statement: You are given an array
The naive solution will just iterate over all divisors. The time complexity
However, we can view each number as a vector of it’s prime divisors. Suppose
It becomes clear that when our array is indexed by this vector, that our operation again becomes a high dimensional prefix sum.
The time complexity would be
Btw, this is actually related to the Riemann Zeta Function. Define the Dirichlet generating function of
Then, we have
Then we can also define the function
Let us figure out what
So
Also, the analogue of or-convolution above is the LCM convolution. The LCM convolution of