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



    For a decimal number x with n digits (A nn-1n-2 ... A 21), we define its weight as F(x) = A n * 2 n-1 + A n-1 * 2 n-2 + ... + A 2 * 2 + A 1 * 1. Now you are given two numbers A and B, please calculate how many numbers are there between 0 and B, inclusive, whose weight is no more than F(A).
    Input
    The first line has a number T (T <= 10000) , indicating the number of test cases. 
    For each test case, there are two numbers A and B (0 <= A,B < 10 9)
    Output
    For every case,you should output "Case #t: " at first, without quotes. The t is the case number starting from 1. Then output the answer.
    Sample Input
    3
    0 100
    1 10
    5 100
    Sample Output
    Case #1: 1
    Case #2: 2
    Case #3: 13
    Hint




    题意:

    我们定义十进制数x的权值为f(x) = a(n)*2^(n-1)+a(n-1)*2(n-2)+...a(2)*2+a(1)*1,a(i)表示十进制数x中第i位的数字。

       题目给出a,b,求出有多少个F(i)(0<=i<=b)不大于f(a)的数。


    基础的数位DP题目


    #include <bits/stdc++.h>
    using namespace std;
    
    int dp[20][10000];  ///dp[i][j]是i位置之前的和小于sum的个数
    int bit[20];
    
    int dfs(int pos,int num,bool flag)
    {
        if(pos == -1)return num >= 0; ///出口
        if(num < 0)return 0;           ///剪枝
    
        if(!flag && dp[pos][num] != -1)
            return dp[pos][num];
    
        int ans = 0;
        int end = flag?bit[pos]:9;
        for(int i = 0;i <= end;i++)
            ans += dfs(pos-1,num - i*(1<<pos),flag && i==end);
    
    
        if(!flag)  dp[pos][num] = ans;
        return ans;
    }
    
    int F(int x)
    {
        int ret = 0;
        int len = 0;
        while(x)
        {
            ret += (x%10)*(1<<len);
            len++;
            x /= 10;
        }
        return ret;
    }
    
    int calc(int A,int B)
    {
        int len = 0;
        while(B)
        {
            bit[len++] = B%10;
            B/=10;
        }
        return dfs(len-1,F(A),1);
    }
    
    int main()
    {
        int T,A,B;
        int iCase = 0;
        scanf("%d",&T);
        memset(dp,-1,sizeof(dp));
        while(T--)
        {
            iCase++;
            scanf("%d%d",&A,&B);
            printf("Case #%d: %d
    ",iCase,calc(A,B));
        }
        return 0;
    }
    





  • 相关阅读:
    luogu P3657 (NOIP2017) 跳房子(二分+DP+单调队列)
    BZOJ 3331 (Tarjan缩点+树上差分)
    Libre OJ 2255 (线段树优化建图+Tarjan缩点+DP)
    LibreOJ 6177 题解(状压DP)
    BZOJ 1179 (Tarjan缩点+DP)
    BZOJ 4919 (树上LIS+启发式合并)
    BZOJ 1100 &&luogu 3454(计算几何+KMP)
    HDU 3228 题解(最小生成树)(Kruskal)(内有详细注释)
    Codeforces 1058C(思维+最大公因数)
    周记 2015.05.30
  • 原文地址:https://www.cnblogs.com/zswbky/p/6792870.html
Copyright © 2011-2022 走看看