URAL 1057 Amount of Degrees (数位dp)

题意:

给出一个范围,求范围内,等于K个B^x的个数,其中x任意。

题解:

这样的式子B^a+B^b+...B^0,很想容易想到进制的转化,我们将某个数R转化为B进制,发现题目所求的个数就是求这个

R转化成的B进制的数范围内满足只有0和1,并且1的个数为K个对应的数的个数。然后身下来就是用dp统计出现次数,剩下的就是陋题了。

#include<iostream>
#include<math.h>
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<vector>
#include<queue>
#include<map>
#include<set>
using namespace std;
#define B(x) (1<<(x))
void cmax(int& a,int b){ if(b>a)a=b; }
void cmin(int& a,int b){ if(b<a)a=b; }
typedef unsigned long long ll;
const int oo=0x3f3f3f3f;
const int MOD=1000000007;
const int maxn=22;
int dp[40][30],bit[40];
int B,K;

int dfs(int pos,int d,int f){
    if(pos<1) return d==K;
    if(!f&&dp[pos][d]!=-1) return dp[pos][d];
    int last= f ? bit[pos] : B-1;
    int res=0;
    for(int i=0;i<=1&&i<=last;i++){
        res+=dfs(pos-1,d+(i==1),f&&i==last);
    }
    if(!f)dp[pos][d]=res;
    return res;
}

int Cnt(int x){
    if(x==0)return 0;
    int len=0;
    while(x){
        bit[++len]=x%B;
        x/=B;
    }
    return dfs(len,0,1);
}

int main(){
/*
#define ON 1
#ifdef ON
    freopen("E:\\read.txt","r",stdin);
#endif // ON
//*/
    int x,y;
    while(scanf("%d %d",&x,&y)!=EOF){
        memset(dp,-1,sizeof dp);
        scanf("%d%d",&K,&B);
        int ans=Cnt(y)-Cnt(x-1);
        printf("%d\n",ans);
    }
	return 0;
}
/**
15 20
2 2
1 100
1 2
1 100
1 3
1 100
1 3
1 100
1 4
1 100
1 5
*/







你可能感兴趣的:(URAL 1057 Amount of Degrees (数位dp))