数位DP统计16进制每个数字出现的次数-模板

使用数位DP,统计任意进制,任意数字出现的次数

input

n,k
n表示16进制中前n个数
k表示数字k出现的次数(11表示A,12表示B,以此类推)

output

ans
ans表示1-n中数字k出现的次数。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+10;
ll a[25];
ll dp[25];
int num;
ll pow16[25];
int chnum;
void init(){
    pow16[0]=1;
    for(int i=1;i<15;i++){
        pow16[i]=16*pow16[i-1];
    }
}
ll dfs(int pos,bool limit,bool lead){
    if(pos==-1)return 0;
    if(!lead&&!limit&&dp[pos]!=-1)return dp[pos];
    int up=limit?a[pos]:15;
    int ans=0;
    for(int i=0;i<=up;i++){
        if(i==chnum){
            if(i==0&&lead){//lead zero
                ans+=dfs(pos-1,limit&&i==a[pos],lead);
                continue;
            }
            if(limit&&i==a[pos])//有限制
            ans+=(num%pow16[pos]+1)+dfs(pos-1,limit&&i==a[pos],lead&&i==0);
            else
            ans+=1*pow16[pos]+dfs(pos-1,limit&&i==a[pos],lead&&i==0);
        }
        else ans+=dfs(pos-1,limit&&i==a[pos],lead&&i==0);
    }
    if(!lead&&!limit)dp[pos]=ans;
    return ans;
}
int solve(int x){
    memset(dp,-1,sizeof(dp));
    int pos=0;
    while(x){
        a[pos++]=x%16;
        x/=16;
    }
    return dfs(pos-1,true,true);
}
int main(){
    init();
    while(cin>>num>>chnum){
        cout<<solve(num)<<endl;
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/gzr2018/p/11766826.html
今日推荐