链接:HDOJ3271
题意:10进制的【A,B】区间内,在转化为BASE进制之后,各个数位的和为M的有多少个数,其中第K个数是多少
思路:转为为BASE进制和转为10进制有什么太大区别吗?
因为BASE不超过10,所以就是在模板的calc函数里改个值就好了
求数位的和为M就是模板
其中第二问:第K个数是多少有点麻烦
首先呢,第1个数是calc(X-1)这样来计算
最大的那个数是calc(Y)
然后就是经典二分搞定
#include<map>
#include<set>
#include<math.h>
#include<time.h>
#include<iostream>
#include<cstdio>
#include<queue>
#include<stack>
#include<stdio.h>
#include<cstring>
#include<string.h>
#include<algorithm>
#include<cstdlib>
using namespace std;
#define lson rt<<1,l,mid
#define rson rt<<1|1,mid+1,r
#define ll rt<<1
#define rr rt<<1|1
#define LL long long
#define ULL unsigned long long
#define maxn 1050
#define maxnum 1000050
#define eps 1e-6
#define input freopen("input.txt","r",stdin)
#define output freopen("output.txt","w",stdout)
#define MOD 1000000007
int BASE,M;
int digit[40];
int dp[40][500];
int dfs(int pos,int sum,bool flag){
if (pos==0) return sum==M;
if (flag&&dp[pos][sum]!=-1) return dp[pos][sum];
int up=flag?BASE-1:digit[pos];
int ans=0;
for(int i=0;i<=up;i++){
int temp=sum+i;
if (temp>M) continue;
ans+=dfs(pos-1,temp,flag||i<up);
}
if (flag) dp[pos][sum]=ans;
return ans;
}
int calc(int num){
if (num<0) return 0;
int len=0;
while(num){
digit[++len]=num%BASE;
num/=BASE;
}
return dfs(len,0,0);
}
int main(){
//input;
int Q,X,Y,K,Case=0;
while(scanf("%d",&Q)!=EOF){
printf("Case %d:\n",++Case);
memset(dp,-1,sizeof(dp));
scanf("%d%d%d%d",&X,&Y,&BASE,&M);
if (X>Y) swap(X,Y);
if (Q==1)
printf("%d\n",calc(Y)-calc(X-1));
else{
scanf("%d",&K);
int l=X,r=Y+1;
int limit=calc(X-1);
while(l<r){
int m=l+(r-l)/2;
if (calc(m)-limit<K)
l=m+1;
else
r=m;
}
if (l==Y+1)
printf("Could not find the Number!\n");
else
printf("%d\n",l);
}
}
return 0;
}