使用数位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;
}