UVA 12063 - Zeros and Ones(数位DP)

博客给出题目链接,题意是求n位(无前导0)且1和0数量相同、值为k倍数的二进制数个数,其中n<=64,k<=100。解题思路采用数位DP,用dp[pos][sum][mod]表示枚举到pos位时0和1相对个数及当前数字mod k的结果,使用记忆化搜索。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目链接 https://cn.vjudge.net/problem/UVA-12063

【题意】
给出n和k(n<=64,k<=100)问你有多少个n位(无前导0)的二进制数的1和0一样多,同时值为k的倍数

【思路】
数位DP,dp[pos][sum][mod]dp[pos][sum][mod] 表示枚举到pos位时数字0和1的相对个数以及当前对应的数字modkmodk 对应的结果,记忆化搜索

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

int n,k;
int a[80];
ll dp[80][160][120];

ll dfs(int pos,int sum,int mod,bool lead,bool limit){
    if(pos==-1){
        if(sum==80 && mod==0) return 1;
        else return 0;
    }
    if(!lead && !limit && dp[pos][sum][mod]!=-1) return dp[pos][sum][mod];

    int up=limit?a[pos]:1;
    ll ans=0;
    for(int i=0;i<=up;++i){
        if(lead && i==0){
            ans+=dfs(pos-1,sum,(mod*2+i)%k,lead,limit && i==up);
        }
        else{
            ans+=dfs(pos-1,sum+(i==0?1:-1),(mod*2+i)%k,lead && 0==i,limit && i==up);
        }
    }
    if(!lead && !limit) dp[pos][sum][mod]=ans;
    return ans;
}

int main(){
    //freopen("in.txt","r",stdin);
    //freopen("out2.txt","w",stdout);
    int T;
    scanf("%d",&T);
    for(int kase=1;kase<=T;++kase){
        scanf("%lld%lld",&n,&k);
        if(0==k){printf("Case %d: 0\n",kase);continue;}
        memset(dp,-1,sizeof(dp));

        for(int i=0;i<n;++i) a[i]=1;
        ll x=dfs(n-1,80,0,true,true);
        a[n-1]=0;
        ll y=dfs(n-1,80,0,true,true);
        printf("Case %d: %lld\n",kase,x-y);
    }
    return 0;
}

转载于:https://www.cnblogs.com/wafish/p/10465204.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值