题解:AT_abc406_e [ABC406E] Popcount Sum 3
同机房大家都写 dfs 就我不这么写。
纯计数。
我们先考虑
那么如果
参考代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
#define N 1000010
#define INF 0x3f3f3f3f
#define lowbit(x) (x&-x)
#define pii pair<int,int>
const ll mod = 998244353;
inline ll qpow(ll base,ll e){ll res=1;while(e){if(e&1)res=res*base%mod;base=base*base%mod;e>>=1;}return res;}
int t,k,cnt,num;ll n,ans,q;
ll f[N],g[N],p[N];
inline ll c(const int &x,const int &y){if(y > x)return 0;return f[x]*g[x-y]%mod*g[y]%mod;}
// 主函数
int main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
cin >> t;f[0] = p[0] = 1;
for(int i = 1;i < N;++i)f[i]=f[i-1]*i%mod,p[i]=p[i-1]*2%mod;g[N-1] = qpow(f[N-1],mod-2);
for(int i = N-2;i >= 0;--i)g[i]=g[i+1]*(i+1)%mod;
while(t--){cin >> n >> k;ans = q = 0;num = 0;
for(int i = 62;i >= 0;--i)if((n&(1ll<<i)))++num;
if(num >= k){for(ll pos = 1;num != k;pos <<= 1)if(n & pos){--num,n&=(~pos);}ans = n;}// 把位置卸掉
else for(ll pos = 1;num != k;pos <<= 1)if(!(n & pos)){++num,n|=pos;}// 补上
for(int i = 62;i >= 0;--i){ll pos = (1ll<<i);if(!(n&pos))continue;
ans = ans + c(i,num)*q%mod + (p[i]-1)*c(i-1,num-1)%mod;ans %= mod;--num;q += pos,q %= mod;
}cout << ans << '\n';
}
return 0;
}