zoukankan      html  css  js  c++  java
  • ural1057 Amount of Degrees ——数位DP

    题目链接:http://acm.timus.ru/problem.aspx?space=1&num=1057

    题目大意:

      意思就是给一个区间[x, y],求这个区间内有多少个恰好可以被k个b的不同次幂的数之和表示出来的数字的个数。

    题目思路:

      只需要求区间[0, m]内的恰好可以被k个b的不同次幂的数之和表示出来的数字的个数,定义这个函数是solve(m, k, b)。题目要求的就是:solve(y, k, b) - solve(x - 1, k, b)。

      思路就是,转化成二进制考虑。把这个区间内的某个数字表示成b进制,要求的数字是转化成b进制之后,每一位的数字均为0或者1,这样的数字。

      画一棵完全二叉树,根节点是0,左子节点是0,右子节点是1,高度从0开始记起,整棵树的根节点不用。则f[i][j]表示,高度为i的二叉树里面恰好含有j个1的数字的个数。那么就有:

      f[i][j] = f[i-1][j-1] + f[i-1][j] 意思就是高度为i的树包含的数字里面,符合条件的数字的数目等于左右两棵子树的和。

    当然数组f[i...n][0]都要初始化为1,因为长度为i...n的并且含有0个1的数字的个数总为1.

    参考解题报告:http://hi.baidu.com/zyz913614263/item/a0215c20efefa01f42634a12

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstdlib>
     4 #include <cstring>
     5 #include <cctype>
     6 #include <stack>
     7 #include <queue>
     8 #include <deque>
     9 #include <map>
    10 #include <set>
    11 #include <vector>
    12 #include <cmath>
    13 #include <algorithm>
    14 #define lson l, m, rt<<1
    15 #define rson m+1, r, rt<<1|1
    16 using namespace std;
    17 typedef long long int LL;
    18 const int MAXN =  0x7fffffff;
    19 const int  MINN =  -0x7fffffff;
    20 const double eps = 1e-9;
    21 const int dir[8][2] = {{0,1},{1,0},{0,-1},{-1,0},{-1,1},
    22   {1,1},{1,-1},{-1,-1}};
    23 int f[32][32];
    24 int solve(int n, int k, int b) {
    25   int a[32], sum, cnt, i, j;
    26   sum = 0; cnt = 0; i = 0;
    27   while (n) {
    28     a[++i] = n%b; n /= b;
    29   }
    30   for (j = i; j >= 1 && cnt <= k; --j) {
    31     if (a[j] > 1) {
    32       sum += f[j][k-cnt]; break;
    33     } else if (a[j] == 1) {
    34       sum += f[j-1][k-cnt]; cnt++;
    35     }
    36     if (j == 1 && cnt == k) sum++;
    37   }
    38   return sum;
    39 }
    40 int main(void){
    41 #ifndef ONLINE_JUDGE
    42   freopen("ural1057.in", "r", stdin);
    43 #endif
    44   int x, y, k, b, i, j;
    45   for (i = 0; i < 32; ++i) f[i][0] = 1;
    46   for (i = 1; i < 32; ++i) 
    47     for (j = 1; j <= i; ++j) 
    48       f[i][j] = f[i-1][j] + f[i-1][j-1];
    49   while (~scanf("%d%d%d%d", &x, &y, &k, &b)) {
    50     printf("%d\n", solve(y, k, b) - solve(x - 1, k, b));
    51   }
    52 
    53   return 0;
    54 }

    看起来代码挺少的,但是其中的思维量不少的。

  • 相关阅读:
    Django 框架
    Git 教程
    Vue详解
    pycharm激活码
    通过元类创建一个Python类
    re模块
    selenium模块
    Beautifulsoup模块基础详解
    requests库
    Urllib库
  • 原文地址:https://www.cnblogs.com/liuxueyang/p/3080069.html
Copyright © 2011-2022 走看看