zoukankan      html  css  js  c++  java
  • hdu 4734 F(x)

    题意:

    对一个数x(A nn-1n-2 ... A 21),定义它的权重为F(x) = A n * 2 n-1 + A n-1 * 2 n-2 + ... + A 2 * 2 + A 1 * 1。

    现在给出A和B,要求计算出0到B的比区间内有多少个数字的权重不超过A的权重。

    思路:

    数位dp。

    一开始定义dp[pos][sum]表示处理到第pos位,前缀和为sum的数字的个数,每次输入都需要清空dp数组,所以tle了。

    其实这个dp的状态是与输入的A有关系的,但是数位dp的本质是与输入的具体数字无关,只与数字的某些状态和特征有关。

    所以改变一下dp的状态,用dp[pos][sum]表示从第0位到第pos位小于等于sum的数字有多少,这样就与输入的数字没有关系了。

    代码:

     1 #include <stdio.h>
     2 #include <string.h>
     3 #include <algorithm>
     4 using namespace std;
     5 int p[15];
     6 int dp[15][1<<13];
     7 int c[15];
     8 int ans;
     9 int cal(int x)
    10 {
    11     int cnt = 0;
    12     int res = 0;
    13     while (x)
    14     {
    15         res += (x % 10) * p[cnt];
    16         x /= 10;
    17         cnt++;
    18     }
    19     return res;
    20 }
    21 int dfs(int pos,int lim,int sta)
    22 {
    23     if (sta < 0) return 0;
    24     if (pos == -1) return 1; 
    25     int mx = lim ? c[pos] : 9;
    26     if (!lim && dp[pos][sta] != -1) return dp[pos][sta];
    27     int res = 0;
    28     for (int i = 0;i <= mx;i++)
    29     {
    30         int cur = sta - i * p[pos];
    31         //printf("pos = %d,cur = %d
    ",pos,cur);
    32         //if (cur > ans) continue;
    33         res += dfs(pos-1,lim && i == mx,cur);
    34     }
    35     if (!lim) return dp[pos][sta] = res;
    36     return res;
    37 }
    38 int solve(int x)
    39 {
    40     int cnt = 0;
    41     while (x)
    42     {
    43         c[cnt++] = x % 10;
    44         x /= 10;
    45     }
    46     int res = dfs(cnt-1,1,ans);
    47     return res;
    48 }
    49 int main()
    50 {
    51     p[0] = 1;
    52     for (int i = 1;i < 15;i++) p[i] = 2 * p[i-1];
    53     int t;
    54     scanf("%d",&t);
    55     int kase = 0;
    56     memset(dp,-1,sizeof(dp));
    57     //solve(1000000000);
    58     while (t--)
    59     {
    60         int a,b;
    61         scanf("%d%d",&a,&b);
    62         ans = cal(a);
    63         //printf("%d
    ",ans);
    64         printf("Case #%d: %d
    ",++kase,solve(b));
    65     }
    66     return 0;
    67 }
  • 相关阅读:
    codeforces 980A Links and Pearls
    zoj 3640 Help Me Escape
    sgu 495 Kids and Prizes
    poj 3071 Football
    hdu 3853 LOOPS
    hdu 4035 Maze
    hdu 4405 Aeroplane chess
    poj 2096 Collecting Bugs
    scu 4444 Travel
    zoj 3870 Team Formation
  • 原文地址:https://www.cnblogs.com/kickit/p/9028706.html
Copyright © 2011-2022 走看看