Given integers $a_0, a_1, ... a_n$, for each $a_i$, find the number of $a_j$ which share no common $1$s with $a_i$ when both $a_i$ and $a_j$ are written in a binary representation.
Another way of expressing the $a_i$ $a_j$ condition is through a logical AND statement: $$a_i \land a_j = 0$$
For any one particular $a_i$, a simple algorithm is to iterate through $a_j$ and checking if $a_i \land a_j = 0$. However, for a very large $n$, this algorithm will not perform well, since its complexity is $O(n^2)$. In my particular use-case, $n > 10^9$, and $a_i < 2^{64}-1$.
Please note, I do realize that this question may be more suitable to stack-overflow, but in my experience I have a better chance of receiving deep answers on math.stack, hopefully that justifies my choice of site.
Any intuition or insight would be much appreciated.
EDIT: I currently do not think this is a right solution.
I think you can make it a bit more general. Let say, you have $n$ numbers, and the representation of any number requires at most $k$ bits (kind of $k = \log n$).
Take all the numbers and store them in the binary tree, where each node represents a suffix. I.e. the root represents an empty suffix. It has two children nodes: one representing a suffix $0$ and the other representing a suffix $1$. Those will have $00$ and $10$, and $01$ and $11$ children respectively. Etc.
While storing the numbers accumulate at each suffix the number of numbers that stored in the subtree rooted at the suffix node. Root will have total number of number, $0$ - the count of numbers that ends in $0$, etc.
Now, take $a_i$ - flip its bits and look up this number - node. Add to this the numbers that were stored directly above.
Example: Suppose, all the numbers $0 - 7$ are given: $000_2, 001_2, 010_2, 011_1, 100_2, 101_2, 110_2, 111_2$. You store numbers (fully expanded to maximum number of bits) in a tree: and count leafs in each subtree (during the store operation - you add a leaf and update the chain back to root). Therefore: the updated counts stored at nodes are:
Note, the order of nodes, I've used to store $0$ bit to the left, and $1$ to the right.
Suppose, you want to lookup $2_{10} = 10_2$. You traverse the tree down to the node with $1_2$ (the non-extended flipped value of $10$) to find $4$.
Storing and extracting will give you $O(n \log n)$, or $O(n \cdot k)$ complexity.