E -popcount sum 3

题目链接:https://atcoder.jp/contests/abc406/tasks/abc406_e

题意:

给定n和k,求[1,n]范围内的数字二进制位1的个数恰好为k的总和

思路:

数位dp

需要记录方案数以及数字和

根据乘法原理,每个位置1对答案的贡献为 该位置的权值(2^(i-1))x后面的方案数

int n,k;
int a[70];
int len,ans;
pii dp[70][70][2];
int vis[70][70][2];
int power[70];
pii dfs(int pos,int cnt,int limit){
    if(pos>len){
        if(cnt==k){
            return {1,0};
        }else return{0,0};
    }
    if(vis[pos][cnt][limit]){
        return dp[pos][cnt][limit];
    }
    vis[pos][cnt][limit]=1;
    pii res;
    int up=limit?a[len-pos+1]:1;
    for(int d=0;d<=up;d++){
        int new_cnt=cnt+(d==1);
        if(new_cnt>k)continue;
        pii temp=dfs(pos+1,new_cnt,limit&&(d==up));
        if(temp.fi==0)continue;
        int weight=power[pos];
        res.fi+=temp.fi;
        res.fi%=mod;
        res.se+=(((d*weight)%mod)*temp.fi)%mod+temp.se%mod;
        res.se%=mod;
    }
    dp[pos][cnt][limit]=res;
    return res;
}
void part(int x){
    len=0;ans=0;
    memset(vis,0,sizeof vis);
    memset(dp,0,sizeof dp);
    while(x){
        a[++len]=x&1;x>>=1;
    }
    for(int i=1;i<=len;i++){
        power[i]=1ll<<(len-i);
    }
    ans=dfs(1,0,1).se;
}
void solve(){
    cin>>n>>k;
    part(n);
    cout<<ans%mod<<endl;
}```
posted @ 2025-05-20 12:38  Marinaco  阅读(18)  评论(0)    收藏  举报
//雪花飘落效果