【算法】【贡献法】

5 阅读1分钟

按位贡献

atcoder.jp/contests/ab…

#include <bits/stdc++.h>  
using namespace std;  
using ll=long long;  
const ll mod=998244353;  
// 函数功能:计算 0 ~ n 中,数字的第 j 位(二进制)是 1 的数的个数  
ll f(ll j,ll n){  
    //从这位有1开始,一直有2^j次向前进位  
    ll p2=(1<<j);// p2 = 2^j  (第j位的权值)  
    ll k=n/(2*p2);// 完整的周期数:每 2^(j+1) 个数为一个周期  
    ll res=k*p2;// 每个周期里,第j位是1的数有 2^j 个  
    ll l=n%(2*p2);// 剩下不满一个周期的数字  
    if(l>=p2){res+=(l-p2+1);}  
    return res;  
}  
void so(){  
      
}int main(){  
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);  
    ll n,m;cin>>n>>m;  
    ll res=0;  
    for(int i=0;i<60;i++){  
        // 如果 M 的第 i 位是 1,这位才会有贡献  
        if(m&(1ll<<i)){  
            res+=f(i,n);  
            res%=mod;  
        }  
    }cout<<res<<'\n';  
}