hdu 3271 SNIBB 数位DP+二分

思路:dp[i][j]:表示第i位在B进制下数字和。

用二分找第k个数!

代码如下:

 1 #include<iostream>
 2 #include<stdio.h>
 3 #include<algorithm>
 4 #include<iomanip>
 5 #include<cmath>
 6 #include<cstring>
 7 #include<vector>
 8 #define ll __int64
 9 using namespace std;
10 int dp[45][310],b,m,bit[45];
11 int dfs(int pos,int mm,bool f)
12 {
13     if(pos==-1) return mm==m;
14     if(!f&&dp[pos][mm]!=-1) return dp[pos][mm];
15     int ans=0;
16     int e=f?bit[pos]:(b-1);
17     for(int i=0;i<=e;i++){
18         ans+=dfs(pos-1,mm+i,f&&i==bit[pos]);
19     }
20     if(!f) dp[pos][mm]=ans;
21     return ans;
22 }
23 int solve(int n)
24 {
25     if(n<=0) return n==m;
26     int s=0;
27     while(n){
28         bit[s++]=n%b;
29         n/=b;
30     }
31     return dfs(s-1,0,1);
32 }
33 int main(){
34     int q,x,y,n,k,ca=0;
35     while(scanf("%d%d%d%d%d",&q,&x,&y,&b,&m)!=EOF){
36         memset(dp,-1,sizeof(dp));
37         printf("Case %d:
",++ca);
38         if(x>y) swap(x,y);
39         if(q==1) printf("%d
",solve(y)-solve(x-1));
40         else{
41             scanf("%d",&k);
42             int low=solve(x-1);
43             int high=solve(y);
44             if(high-low<k){
45                 puts("Could not find the Number!");
46                 continue;
47             }
48             int l=x,r=y,mid,ans=0;
49             while(l<=r){
50                 mid=(int)(((ll)l+(ll)r)>>1);
51                 int t=solve(mid);
52                 if(t-low>=k) r=mid-1,ans=mid;
53                 else l=mid+1;
54             }
55             printf("%d
",ans);
56         }
57     }
58     return 0;
59 }
View Code
原文地址:https://www.cnblogs.com/xin-hua/p/3319051.html