题目链接:点击打开链接
题目大意:求给定区间[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.
1 ≤ X ≤ Y ≤ 2^31−1,1 ≤ K ≤ 20, 2 ≤ B ≤ 10。
思路:数位DP的思想, 因为本题满足区间减法, 所以我们只需要求出一个不大于n的满足要求的数的个数,那么先预处理出一个B进制数列,那么n可以用bit[0]*B^0 + bit[1]*B^1 + ..... + bit[m]*B^m表示,以为每个B的幂只能出现一次, 所以 用d[i][j][p]表示B进制数当前第i位,目前有j项, 是等于n还是小于n 的方法数。
细节参见代码:
#include<cstdio> #include<cstring> #include<algorithm> #include<iostream> #include<string> #include<vector> #include<stack> #include<bitset> #include<cstdlib> #include<cmath> #include<set> #include<list> #include<deque> #include<map> #include<queue> #define Max(a,b) ((a)>(b)?(a):(b)) #define Min(a,b) ((a)<(b)?(a):(b)) using namespace std; typedef long long ll; typedef long double ld; const ld eps = 1e-9, PI = 3.1415926535897932384626433832795; const int mod = 1000000000 + 7; const int INF = 0x3f3f3f3f; // & 0x7FFFFFFF const int seed = 131; const ll INF64 = ll(1e18); const int maxn = 55; int T,n,m,x,y,kase,k,b,len,vis[maxn][maxn][2],d[maxn][maxn][2],bit[maxn],bb[maxn]; void init(ll n) { len = 0; while(n) { bb[++len] = n % b; n /= b; } for(int i=1;i<=len;i++) bit[i] = bb[len-i+1]; } int dp(int pos, int j, int p) { int& ans = d[pos][j][p]; if(pos == len + 1) return j == k; if(vis[pos][j][p] == kase) return ans; vis[pos][j][p] = kase; ans = 0; for(int i=0;i<=1;i++) { if(p) { ans += dp(pos+1, j+i, p); } else { if(i == bit[pos]) ans += dp(pos+1, j+i, p); else if(i < bit[pos]) ans += dp(pos+1, j+i, p^1); } } return ans; } int main() { while(~scanf("%d%d%d%d",&x,&y,&k,&b)) { init(y); ++kase; ll r = dp(1, 0, 0); init(x-1); ++kase; ll l = dp(1, 0, 0); printf("%d\n",r - l); } return 0; }