zoukankan      html  css  js  c++  java
  • HDU-4734 F(x)数位dp

    原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=4734

    大致意思就是每次询问【0,b】区间有多少数的f(i) <= f(a)

    这题有一个巧妙的状态定义方式:dp[pos][sum]表示枚举到第pos位,【还需要】sum才能达到f(a)

    1e9的数据范围,sum不超过5000。最后只要sum >= 0就表示不超过f(a)

    状态依旧与输入的a无关:如果a改变了,dfs传入的sum改变,而枚举pos位得到sum是数本身的性质,所以还是在开头memset

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 using namespace std;
     5 
     6 int a[15], dp[15][5000];
     7 
     8 int f(int k){
     9     int ans = 0, pos = 0;
    10     while (k){
    11         ans += (k%10)*(1<<pos);
    12         k /= 10;
    13         pos++;
    14     }
    15     return ans;
    16 }
    17 
    18 int dfs(int pos, int sum, bool lim){
    19     if (pos == -1) return sum >= 0;
    20     if (sum < 0) return 0;
    21     if (!lim && dp[pos][sum] != -1) return dp[pos][sum];
    22     int ans = 0;
    23     int r = lim ? a[pos] : 9;
    24     for (int i = 0; i <= r; i++){
    25         ans += dfs(pos-1, sum - i*(1<<pos), lim && i == a[pos]);
    26     }
    27     if (!lim) dp[pos][sum] = ans;
    28     return ans;
    29 }
    30 
    31 int solve(int k, int b){
    32     k = f(k);
    33     int pos = 0;
    34     while (b){
    35         a[pos++] = b % 10;
    36         b /= 10;
    37     }
    38     return dfs(pos-1, k, 1);
    39 }
    40 
    41 int main(){
    42     int t, kase = 0, k, b;
    43     scanf("%d", &t);
    44     memset(dp, -1, sizeof dp);
    45     while (t--){
    46         scanf("%d%d", &k, &b);
    47         printf("Case #%d: %d
    ", ++kase, solve(k, b));
    48     }
    49     return 0;
    50 }
  • 相关阅读:
    hdu 1875 Krustal最小生成树
    寒假学习PID和latex随笔2013/2/10
    HDU:今年暑假不AC
    HDU:七夕节
    寒假规划
    HDU:开门人和关门人
    HDU:cake
    HDU:最小公倍数
    HDU:Who's in the Middle
    Latex 第一个程序 效果
  • 原文地址:https://www.cnblogs.com/QAQorz/p/9360819.html
Copyright © 2011-2022 走看看