At356 D - Masked Popcount
D.Masked Popcount
题意简述
给你两个数 \(N\) 和 \(M\), 计算 \(\displaystyle \sum_{k=0}^{N}\) \(\rm{popcount}\)\((k \mathbin{\&} M)\), 其中popcount是二进制中1的个数,结果在模 \(998244353\)下表示.
解题思路
要求计算0~N中所有数与M按位与后位1的数的个数,不妨拆位考虑,如果第 \(i\) 位\(M\)是0,这一位对结果的贡献一定是0,如果第 \(i\) 位是 1,他对结果的贡献分为两部分考虑,第一部分 \(i\) 右边的二进制位是任意选择的,\(i\) 左边的二进制位可选择 $ [0,(N>>i+1)-1]$共 \((N>>i+1)\) 种,有第一种贡献为 \((1<<i)·(N>>i+1)\),而第二种贡献左边是 $ [(N>>i+1),(N>>i+1)]$ 共 \(1\) 种,右边的选择是右边的贡献是 \([0,N\\\&( (1<<i)-1)]\) 共 $ N\&((1<<i)-1)+1 $ 种.
AC code
#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
typedef long long ll;
const ll mod=998244353;
int main(){
cin.tie(0)->ios_base::sync_with_stdio(false);
ll n,m;cin>>n>>m;
ll ans=0;
auto calc=[&](ll x) ->ll {
ll r=(1LL<<x);
ll l=n/(r*2LL);
ll res=l*r%mod;
if(n&r) res=(res+((r-1)&n)+1)%mod;
return res;
};
for(int i=0;i<=60;i++){
if(m>>i&1) ans=(ans+calc(i))%mod;
}
cout<<ans<<endl;
return 0;
}

浙公网安备 33010602011771号