Official

D - Masked Popcount Editorial by en_translator


In this editorial, we use the following expressions.

The \(j\)-th bit of \(x\): the \(2^j\)s place of \(x\) in its binary representation.
The \(j\)-th bit of \(x\) is set: the \(2^j\)s place of \(x\) in its binary representation is \(1\).


The expression can be deformed as follows.

\(\displaystyle \sum_{k=0}^{N} \rm{popcount}\)\((k \mathbin{\&} M) = \) \(\displaystyle \sum_{k=0}^{N} (\) the number of bits set in \((k \mathbin{\&} M))\)
\(\displaystyle = \sum_{k=0}^{N} \sum_{j=0}^{\infty}\) \((1\) if the \(j\)-th bit of \((k \mathbin{\&} M)\) is set, and \(0\) otherwise\()\)
\(\displaystyle = \sum_{j=0}^{\infty} \sum_{k=0}^{N}\) \((1\) if the \(j\)-th bit of \((k \mathbin{\&} M)\) is set, and \(0\) otherwise\()\).

\((1\) if the \(j\)-th bit of \((k \mathbin{\&} M)\) is set, and \(0\) otherwise\()\) can be rephrased as follows.

  • If the \(j\)-th bit of \(M\) is not set, always \(0\).
  • If the \(j\)-th bit of \(M\) is set:
    • if the \(j\)-th bit of \(k\) is set, \(1\).
    • if the \(j\)-th bit of \(k\) is not set, \(0\).

Under the constraints of this problem, the \(60\)-th and higher bits of \(M\) is always \(0\), so the sought sum can be found by the following procedure.

  • For \(j=0,1,\dots,59\), repeat the following:
    • If the \(j\)-th bit of \(M\) is not set, do nothing.
    • If the \(j\)-th bit of \(M\) is set, add the number of integers between \(0\) and \(N\) (inclusive) whose \(j\)-th bit is set to the answer.

All that left is to count the following:

Among the integers between \(0\) and \(N\) (inclusive), how many has the \(j\)-th bit set?

For instance, consider \(j=2\).
The integers with the \(2\)-nd bit set are \(4,5,6,7,12,13,14,15,20,21,22,23,28\dots\).
If you closely look at this sequence, we notice the following fact:

  • For a non-negative integer \(k\), among the integers between \(0\) (inclusive) and \(k \times 2^{j+1}\) (exclusive), there are \(k \times 2^j\) integers whose \(j\)-th bit is set.

This can be proved by the facts that the \(j\)-th bit of \(i\) and \(i+2^{j+1}\) coincide for all non-negative integers \(j\), and that there are exactly \(2^j\) integers between \(0\) (inclusive) and \(2^{j+1}\) (exclusive) whose \(j\)-th bit is set.

Moreover, we have the following fact:

  • Let \(k\) be a non-negative integer and \(l\) be an integer strictly less than \(k \times 2^{j+1}\); then among the integers between \(k \times 2^{j+1}\) (inclusive) and \(k \times 2^{j+1} + l\) (exclusive), the number of integers whose \(j\)-th bit is set is:
    • \(0\) if \(l\) is strictly less than \(2^j\);
    • \(l - 2^j + 1\) if \(l\) is greater than or equal to \(2^j\).

By combining these two, one can find the number of integers between \(0\) and \(N\) (inclusive) whose \(j\)-th bit is set.

Hence, the problem has been solved.
Note that since the answer may not fit in \(64\)-bit integer type, you must be cautious when finding the remainder modulo \(998244353\).

Sample code 1 (C++):

#include<bits/stdc++.h>
#define mod 998244353

using namespace std;

long long f(long long j,long long n){
  long long p2=(1ll<<j); // 2^j
  long long k=n/(2*p2);
  long long res=k*p2;
  long long l=n%(2*p2);
  if(l>=p2){
    res+=(l-p2+1);
  }
  return res;
}

int main(){
  long long n,m;
  cin >> n >> m;
  long long res=0;
  for(long long i=0;i<60;i++){
    if(m&(1ll<<i)){
      res+=f(i,n);
      res%=mod;
    }
  }
  cout << res << "\n";
  return 0;
}

Sample code that uses bit operations is as follows.

Sample code 2 (C++):

#include<bits/stdc++.h>
#define mod 998244353

using namespace std;

long long f(long long j,long long n){
  long long res=((n>>(j+1))<<j);
  if(n&(1ll<<j)){
    res+=((n&((1ll<<j)-1))+1);
  }
  return res;
}

int main(){
  long long n,m;
  cin >> n >> m;
  long long res=0;
  for(long long i=0;i<60;i++){
    if(m&(1ll<<i)){
      res+=f(i,n);
      res%=mod;
    }
  }
  cout << res << "\n";
  return 0;
}

posted:
last update: