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;
}
posted @ 2025-05-24 12:12  usedchang  阅读(11)  评论(0)    收藏  举报