This is the kind of editorial which might scare people. It is very nice and probably, the setter made the question with this approach in mind when a much simpler approach was available.
I used this logic:
First query 2^{20}, and store this sum as a reference point. Also, this tells us the parity of the first (least significant) bit. Notice that under the given constraints, none of the elements of the hidden numbers will have the 20^{th} bit occupied. So, if we subtract n*2^{20} from the input, the sum will be the same as obtained by querying for 0. Let the input for 2^{20} be A.
Now query 2^i \forall i \in [1, 19]. Notice that when you xor any number by 2^i, its i^{th} bit gets flipped.
Say there are n numbers with the i^{th} bit turned on and m numbers with the bit turned of. When you queried 2^{20}, the i^{th} bit contributed 2^i*n to the sum and when you query 2^i, it contributes 2^i * m to the sum while the contribution of the other bits does not change. Let the input for 2^i be B.
A-B = 2^i*(n- m)
Thus, n-m = \dfrac{A-B}{2^i}
Also, the total number of elements in the hidden array are n+m = N.
Then n = \dfrac{N + \dfrac{A-B}{2^i}}{2}
If the parity of set bits is odd, then the bit will be set in the final xor as well, else it will not be set.
Code
for (int t = 0; t < tc; t++){
int n;
cin >> n;
ll ans1 = 0;
ll sum;
cout << 1 << " " << 1048576 << endl;
cin >> sum;
sum -= n*1048576;
if(sum%2) ans1 = 1;
for(int i = 1; i <= 19; i++){
cout << 1 << " " << (1 << i) << endl;
ll sum1;
cin >> sum1;
ll diff = sum - sum1;
diff = diff/(1LL << i);
ll on = (n + diff)/2;
if(on%2 == 1) ans1 |= (1 << i);
}
cout << 2 << " " << ans1 << endl;
int j;
cin >> j;
assert(j == 1);
}
In the code, N is denoted n, A by sum, B by sum1 and n by on
