CS2023_PON - Editorial

PROBLEM LINK:

Practice
Contest: Division 1
Contest: Division 2
Contest: Division 3
Contest: Division 4

Author: himanshu154
Tester: jay_1048576
Editorialist: iceknight1093

DIFFICULTY:

TBD

PREREQUISITES:

Familiarity with bitwise AND

PROBLEM:

Given an array A and an integer B, does there exist a subsequence of A whose bitwise AND equals B?

EXPLANATION:

First, recall the following property of bitwise AND:

\text{If \ } x \ \&\ y = z, \text{ then } x \ \&\ z = z \text{ and } y\ \&\ z = z.

That is, if x\ \&\ y = z, then both x and y will be supermasks of z (meaning any bit set in z will also be set in x and y).

This of course extends to the bitwise AND of several values as well:
If x_1 \ \&\ x_2\ \&\ \ldots \ \&\ x_k = y, then each x_i will be a supermask of y.


Let’s look at the above property from the perspective of the problem we want to solve.
We want to figure out whether there’s a subsequence of A such that its bitwise AND equals B.

That is, we want to know whether there exist indices 1 \leq i_1 \lt i_2 \lt \ldots \lt i_k \leq N such that

A_{i_1}\ \&\ A_{i_2}\ \&\ \ldots\ \&\ A_{i_k} = B

Immediately, the first property tells us that each A_{i_j} will be a supermask of B.
So, we only care about those values in A that are supermasks of B.

Let S be the set of values in A that are supermasks of B.
Then, in fact S is the subsequence we’re looking for!

That is, if the bitwise AND of the values in S equals B, the answer is Yes.
Otherwise, the answer is No.

Why?

If the bitwise AND of S equals B, obviously the answer is Yes since we directly found a valid subsequence.

Now, suppose the bitwise AND of S doesn’t equal B.
Since every element of S has B as a submask, clearly their AND must also have B as a submask.
However, since it doesn’t equal B, the AND must also be a strict supermask of B — that is, there exists some bit k such that B doesn’t have k set; but every element of S does have k set.

Now, consider an arbitrary subsequence of A.

  • If this subsequence includes an element outside S, clearly its bitwise AND cannot be B (by definition of S).
  • If this subsequence is fully contained in S, then its AND will have bit k set for sure; and so cannot equal B anyway.

So, no subsequence has a bitwise AND of B, as claimed.

This gives a simple linear solution: find the bitwise AND of all supermasks of B, and check if it equals B or not.

TIME COMPLEXITY

\mathcal{O}(N) per testcase.

CODE:

Setter's code (C++)
#include <bits/stdc++.h>
using namespace std;
#define int long long int
#define rep(i,a,b) for(int i=a;i<b;i++)

void solve(){
	int n,b;
	cin>>n>>b;
	vector<int> arr(n);
	rep(i,0,n) cin>>arr[i];

	int res_and=(1LL<<31)-1;
	int cnt=0;
	rep(i,0,n){
		if((arr[i]&b) == b){
			res_and = res_and & arr[i];
			cnt++;
		}
	}

	if(res_and == b && cnt>0){
		cout<<"YES"<<endl;
	}else{
		cout<<"NO"<<endl;
	}
}

int32_t main() {
	auto begin = std::chrono::high_resolution_clock::now();
	ios_base::sync_with_stdio(false);
	cin.tie(0); cout.tie(0); 

	#ifndef ONLINE_JUDGE
	freopen("D:/Desktop/Test_CPP/CS2023_PON/CS2023_PON_3.in", "r", stdin);
	freopen("D:/Desktop/Test_CPP/CS2023_PON/CS2023_PON_3.out", "w", stdout);
	#endif

    int t=1;
	cin>>t;
	while(t--){
		solve();
	}

	auto end = std::chrono::high_resolution_clock::now();
    auto elapsed = std::chrono::duration_cast<std::chrono::nanoseconds>(end - begin);
    cerr << "Time measured: " << elapsed.count() * 1e-6 << "ms\n"; 
	return 0;
}

Tester's code (C++)
/*...................................................................*
 *............___..................___.....____...______......___....*
 *.../|....../...\........./|...../...\...|.............|..../...\...*
 *../.|...../.....\......./.|....|.....|..|.............|.../........*
 *....|....|.......|...../..|....|.....|..|............/...|.........*
 *....|....|.......|..../...|.....\___/...|___......../....|..___....*
 *....|....|.......|.../....|...../...\.......\....../.....|./...\...*
 *....|....|.......|../_____|__..|.....|.......|..../......|/.....\..*
 *....|.....\...../.........|....|.....|.......|.../........\...../..*
 *..__|__....\___/..........|.....\___/...\___/.../..........\___/...*
 *...................................................................*
 */
 
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define INF 1000000000000000000
#define MOD 1000000007

void solve(int tc)
{
    int n,b;
    cin >> n >> b;
    int a[n];
    for(int i=0;i<n;i++)
        cin >> a[i];
    int c = INT_MAX;
    for(int i=0;i<n;i++)
    {
        if((a[i]|b)==a[i])
            c &= a[i];
    }
    if(c==b)
        cout << "YES\n";
    else
        cout << "NO\n";
}

int32_t main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);
    int tc=1;
    cin >> tc;
    for(int ttc=1;ttc<=tc;ttc++)
        solve(ttc);
    return 0;
}
Editorialist's code (Python)
for _ in range(int(input())):
    n, b = map(int, input().split())
    have = 2**31 - 1
    for x in list(map(int, input().split())):
        if x&b == b: have &= x
    print('Yes' if have == b else 'No')
4 Likes

I’ve written exactly the same code during the contest and it was giving error in the last test case. I was frustrated. Contest ended and I saw the setter’s and tester’s code. It was exactly the same. Moreover I even copy pasted the setter’s code and submitted. The same thing happened again, the last test case was giving wrong answer. How are people even submitting correctly?

2 Likes
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define rep(i, a, b) for (int i = a; i < b; i++)
#define pb push_back
#define vi vector<int>
#define vvi vector<vector<int>>
#define all(v) (v).begin(), (v).end()
#define umapii unordered_map<int, int>
#define m 1000000007
vector<bool> prime;

ll binpow(ll b, ll a)
{
    if (b == 0)
        return 1LL;
    ll res = binpow(a, b / 2);
    if (b % 2)
        return res * res * a;
    else
        return res * res;
}

ll modpow(ll reqp, ll i)
{
    if (reqp == 0)
        return 1LL;
    ll u = modpow(reqp / 2, i);
    u = (u * u);
    if (reqp % 2 != 0)
        u = (u * i);
    return u;
}

void SieveOfEratosthenes(int n)
{
    for (int p = 2; p * p <= n; p++)
    {
        if (prime[p] == true)
        {
            for (int i = p * p; i <= n; i += p)
                prime[i] = false;
        }
    }
}

ll factorial(ll n)
{
    if (n == 1)
        return 1LL;
    return n * factorial(n - 1);
}
ll modfactorial(ll n)
{
    if (n == 1)
        return 1LL;
    return (n * factorial(n - 1)) % m;
}

int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);

    int t;
    cin >> t;
    while (t--)
    {
        ll n, targ;
        cin >> n >> targ;
        vector<ll> v;
        rep(i, 0, n)
        {
            ll x;
            cin >> x;
            v.pb(x);
        }
       
            if (targ != 0)
            {

               
                ll cnt(0);
                rep(i, 0, n)
                {
                    if ((targ & v[i]) ==targ)
                        cnt++;
                    if(targ==v[i]){cnt=3;}
                }
                if (cnt >= 2)
                    cout << "YES" << endl;
                else
                    cout << "NO" << endl;
            }
            else
            {
                ll temp=(1LL<<30)-1LL;
                rep (i,0, n)
                {
                    temp = (v[i] & temp);
                    if(temp==0)break;
                }
                if (temp == 0)
                    cout << "YES" << endl;
                else
                    cout << "NO" << endl;
            }
        }
    
    return 0;
}

could someone please tell me where am i failing,the logic is same i guess please help me find any bug or logic error :pray: :pray: :pray: :pray: :pray: :sleepy: :smiling_face_with_tear: :smiling_face_with_tear: :smiling_face_with_tear:
we need atleast 2 numbers whose bitwise and is equal to target if the target number is not in the array itself…for target 0 i am solving it seperately…i couldn’t find where the issue is…please help me out in this!!!
of someone can give me any testcase where my code falis then that would be really helpful

My bad, I pasted old (and as it happens, wrong) code in the editorial (both the setter’s and the tester’s).
Testcases were updated after that to catch the error; the code in the post is also updated now.

The issue is the value you took as ‘infinity’ being 2^{30} - 1.

Consider for example a testcase with N = 1, B = 2^{30}-1, A_1 = 1.
Your code prints Yes, is that really the case?

2 Likes

yes happened with me as well. I changed mask to -1 then got AC.

funny thing is i am passing only the last testcase…totally opposite for me

I tried solving this problem in some other way in linear complexity,
I checked if there’s one number with same number of leading zeros as that of the k and checked if there exists one number (atleast) which has same bits that of the number k,

but I am getting TLE in this, can anyone explain to me why ? This is link to solution : solution

Your logic doesn’t look correct at all.
The number of elements that are submasks of B doesn’t really matter at all, for example

1
5 1
3 3 3 3 3

Please read the editorial.

thanks…i missed that

The TLE is because you’re printing too much, comment out the debug statements and it’ll run fast.
Of course, your logic is still wrong so you’ll receive a WA verdict.

I am getting wrong answer on first and third testcase. However I am unable to find where my code is failing.
I first found all the elements in the numbers that got 1 in binary representation wherever B have 1.
Then if the bitwise & of all such elements is equal to B then print YES otherwise the answer is NO.
My code is also passing the case when B= 2^30-1 and Ai=1

This is how I did it: CodeChef: Practical coding for everyone

I think this implementation is pretty good or understanding each case. I used multiset of elements and kept removing bad ones.

You can refer here for the full idea: In CS2023_PON problem, Can you please help me with where's my approach of solving goes wrong - #2 by math_pi