数的度(数位dp)

原题来自:NEERC 2000 Central Subregional,题面详见 Ural 1057

求给定区间 [X,Y]中满足下列条件的整数个数:这个数恰好等于 K个互不相等的 B 的整数次幂之和。例如,设 X=15,Y=20,K=2,B=2,则有且仅有下列三个数满足题意:

17=2^4+2^0 18=2^4+2^1 20=2^4+2^2

Input

第一行包含两个整数 X 和 Y,接下来两行包含整数 K 和 B。

Output

只包含一个整数,表示满足条件的数的个数。

Example

样例输入

15 20
2
2

样例输出

3

Hint

对于全部数据,1XY2311,1K20,2B10

#include<bits/stdc++.h>
using namespace std;
int read() {
    int x=0; int f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9') {if(ch=='-') f=-1; ch=getchar();}
    while(ch>='0'&&ch<='9') {x=x*10+ch-'0'; ch=getchar();}
    return x*f;
}
const int maxn=31;
int a[maxn][maxn];
int n,m,k,b;
void inint(){
    a[0][0]=1;
    for(int i=0;i<=maxn;i++){
        a[i][0]=1; 
        for(int j=1;j<=i;j++){
            a[i][j]=a[i-1][j]+a[i-1][j-1];
        }
    }
} 
int dp(int n){
    if(n==0){
        return 0;
    }
    vector<int>nums;
    while(n){
        nums.push_back(n%b),n/=b;
    }
    int last=0;
    int res=0;
    for(int i=nums.size()-1;i>=0;i--){
        int x=nums[i];    
        if(x){//左边 
            res+=a[i][k-last];
            if(x>1){
                res+=a[i][k-last-1]; 
                break; 
            }
            else if(x==1){
                last++; 
                if(last>k){
                    break;
                }
            }
        }
        if(last>k){
            break;
        }
        if(!i&&last==k){
            res++;
        } 
    }
    return res; 
}
int main(){
    inint();
    cin>>n>>m>>k>>b; 
    cout<<dp(m)-dp(n-1)<<endl; 
} 
原文地址:https://www.cnblogs.com/lipu123/p/13323773.html