Ural 1057 Amount of Degrees(数位DP)

题目链接:点击打开链接

题目大意:求给定区间[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;
}


你可能感兴趣的:(ACM-ICPC,ural,数位dp)