FINXOR - Editorial

I’m surprised to see Gaussian eliminations and matrixes and stuff, it’s actually quite simple. The main observation/step is the following:
If we first query some X, and than query Y = (X ^ (1 << b)) (same as X, except on position b), we get:
All positions except b will be same everywhere, so their contribution to both sums will be the same.
So, if we subtract these 2 sums, we find 2^b * (ones(b) - zeroes(b)). On the other hand, ones(b) + zeroes(b) = n, meaning we uniquely find number of 1 bits on position b in numbers (A[i] XOR X). We can choose X so that it has all 0-s in positions 0,…,19.

I omitted a few small details, but here’s my solution - CodeChef: Practical coding for everyone.

1 Like

CAN SOMEBODY PLEASE HELP ME OUT WITH THIS. I DON’T UNDERSTAND SO AS TO WHAT IS WRONG IN MY LOGIC.
I WAS WAITING FOR 4 DAYS FOR THE CONTEST TO GET OVER AND I BE ABLE TO DISCUSS THE SOLUTION. GOT ANXIETY LEVEL PRO MAX XD

#i nclude < bits / stdc++.h >
using namespace std;

int main()
{
int t;
cin>>t;
long long int arr[22]={1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
for (int i=1;i<21;i++)
{
arr[i]=2*arr[i-1];
}
for(int z=t;z>0;z–)
{
int n;
cin>>n;
cout<<1<<" “<<arr[20];
int ans;
cin>>ans;
ans=ans-(arr[20]*n);
int func = 0;
if (ans%2!=0)
{
func=func+1;
}
for (int i=0;i<20;i++)
{
int ansu;
ansu=ans+(arr[i]*n);
cout<<1<<” “<<arr[i];
int tans;
cin>>tans;
if (((ansu-tans)/(arr[i]*2))%2 !=0)
{
func=func+arr[i];
}
}
cout<<2<<” "<<func<<endl;
int end;
cin>>end;
}
}

Here is my simple solution using python.

import sys
def readArr():
	return [int(x) for x in input().split()]

def ask(what):
	print(1,what,flush=True)
	reply = int(input())
	if reply == -1:
		sys.exit(1)
	return reply

def solve():
	N = int(input())
	k = 2**20 - 1
	sm = (N*k - ask(k)) #o+e=n
	ans = 0
	to_use = 0
	for i in range(19):
		n = 2**i;
		tmp = (ask(n) - sm)
		to_use += tmp
		tmp //= n
		ones = (N - tmp) // 2
		#print("tmp",tmp,"ones",ones)
		ans += n*(ones%2)
		#print("ans now",ans)
	#power 19
	mytmp = ((N*k - sm) - to_use - sm) // (2**19)
	ans += (((N-mytmp) // 2) % 2) * (2**19)

	print(2,ans,flush=True)
	flag = int(input())
	if flag == -1:
		sys.exit(1)

if __name__ == "__main__":
	# T = 1
	T = int(input())
	for t in range(T):
		solve()
1 Like

thats what is used there in my code

2 Likes

I think It Should be:
Lets, define x_{k} for 0<=k<=19, as the number of elements in array A with kth bit “OFF”.

Because if the 2^i th bit is OFF,then only it will contribute to q_{i}

@krikti
Can You Correct me?

No, the statement is correct.

Try to verify this by taking a small example. :slight_smile:

1 Like

Nice Approach. :slight_smile:

Even during the contest, I was bit surprised seeing majority candidates using similar approach, which I might have missed.

By the way one quick question, If the limitation on maximum value of K was set as 2^{19}, would that effect the logic ?

I have done it for (2^19) + 1. Don’t know for 2^19.
Instead of 2^20 we use 2^0 as reference, which i used during contest.
My Solution

Edit: Allowing query 0 with 2^19 constraint will pass

Yes, I’ve used the same logic.

I totally agree with you on this and that’s the same logic I’ve used in my code.

I think if 0 and 2^20 are both not allowed, then we would have to make a slight modification. We would query 1 first and then check the parity of sum - N. Also, we would have had to use 2^i + 1 everywhere, thus it would only be solvable by this approach for K <= 2^19 + 1, if 0 is not allowed.

You have asked 21 Questions?
Also you are not flushing the o/p here:

cout<<1<<" “<<arr[20];

You have to flush output after every output and you used one query above the loop, you had 19 remaining and you used 20 inside the loop. The loop runs 20 times. I don’t know about the logical part of your solution, but these were the few mistakes i could find, I hope it helps!

1 Like

@krikti For Solving this Problem through Gauss Elimination , Should we follow this : Click Here ?

Getting WA in 2nd subtask.
Someone please help!!!

#include<bits/stdc++.h>
using namespace std;
int main()
{
long long t,n,sum,s,k,i,reply,no,out,tm,tp,extra;
cin>>t;
while(t–)
{
cin>>n;
cout<<“1 1048576”<<endl;
cin>>sum;
sum=sum-n1048576;
k=i=1;
s=0;
while(i<20)
{
cout<<"1 "<<k<<endl;
cin>>reply;
if(reply-sum == n
k)
goto skip;
if(reply==-1)
exit(0);
extra=(reply-sum)/k;
if(extra>0)
{
tp=extra+(n-extra)/2;
tm=n-tp;
}
else if(extra==0)
{
tp=tm=n/2;
}
else
{
tm=abs(extra)+(n-abs(extra))/2;
tp=n-tm;
}
if(tm % 2)
s^=k;
skip:;
k*=2;
i++;
}
cout<<"2 "<<s<<endl;
cout.flush();
cin>>out;
}
}

can you briefly explain what you have done ?

But here in this case there is no way of knowing if the last bit is set on not…
From the bit 1 we can see if it should be set or not…

the last bit that is 2^20 th bit will not count as 10^6 has elements till 2^19th bit

1 Like

in ur code u r strating with k=1 so the highset bit is 18 upto which the the while loop will run & every time the 19’th bit will be skkiped , so it was obvious to get a WA.

@krikti i have solved , assuming that k<=10^6 then the code would slightly change…
here is my solution->CodeChef: Practical coding for everyone

@wm101
Your Explaination was great!
Can you please tell that How you computed the generalised inverse of the matrix?