• URAL 1057 Amount of Degrees (数位DP)


    题意

    求给定区间[X,Y]中满足下列条件的整数个数:这个数恰好等于K 个互不相等的B的整数次幂之和。

    思路

    第一道数位DP题,参考09年国家集训队论文《浅谈数位类统计问题》。 这类问题的第一步一般都先把区间[X,Y]转化为区间[1,X]和[1,Y]。 【重要思想---数形结合、按位处理】按照数的二进制位构建一个类似Trie树的一个二进制树,在树上进行位操作。树的每一层对应每一位。 我们先来看2进制。在这道题中,我们用f[i][j]表示高度为i含有j个1的树的个数(设叶子节点高度为0,且f[0][0] = 1),tot表示当前路径根节点上已经有的1的个数。对于一个数x,我们在它的二进制树上操作,遇到0左拐,遇到1右拐(进入右子树),并且计算它的左兄弟子树中有K-tot个1的个数,再将tot+1。如下图所示,红色为x的路径,蓝绿紫三个子树分别是三次右拐时计算的子树。 URAL 1057 数位DP 而处理大于2进制位的B进制位时,把它当作二进制位处理即可:我们先需要把每位的数值都转化为1或0。我们只需要向下找最大的符合条件的那个数,就是从左寻找第一个不是0或1的数,然后把右边的每位数字都改为1。构建好二进制数以后,按位DP即可。注意最后要是n也满足条件,也要加上去。

    代码

      [cpp] #include #include #include #include #include #include #include #include #include #define MID(x,y) ((x+y)/2) #define MEM(a,b) memset(a,b,sizeof(a)) #define REP(i, begin, m) for (int i = begin; i < begin+m; i ++) using namespace std; int f[35][35]; void init(){ int n = 31; f[0][0] = 1; REP(i, 1, n){ f[i][0] = f[i-1][0]; REP(j, 1, i){ f[i][j] = f[i-1][j] + f[i-1][j-1]; } } } int change_to_bin(int x, int b){ vector v; while(x){ v.push_back(x%b); x /= b; } for (int i = (int)v.size()-1; i >= 0; i --){ if (v[i] > 1){ for (int j = i; j >= 0; j --){ v[j] = 1; } break; } } int ans = 0; for (int i = 0; i < (int)v.size(); i ++){ ans += v[i] * (1 << i); } return ans; } int cal(int x, int k){ int num = 0, tot = 0; for (int i = 30; i >= 0; i --){ if (x & (1< k) break; x = x^(1<
  • 相关阅读:
    C# Using MySQL
    C++ Asynchronous IO on Windows
    C++ Bind adapter usage
    C# Entity Framework with MSSQL, MYSQL
    Read a file into array for C++/C#
    上下移动 04.16
    盒子模型001基础
    JavaScript&JQ 001_五角星评分
    jQuery EasyUI tree的 使用
    自定义实现URL重写 04.18
  • 原文地址:https://www.cnblogs.com/AbandonZHANG/p/4114093.html
Copyright © 2020-2023  润新知