HDU4734 F(x)(数位DP)

来源:互联网 发布:物流企业利润率的算法 编辑:程序博客网 时间:2024/06/05 21:12

F(x)

Time Limit: 1000/500 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 5850    Accepted Submission(s): 2208


Problem Description
For a decimal number x with n digits (AnAn-1An-2 ... A2A1), we define its weight as F(x) = An * 2n-1 + An-1 * 2n-2 + ... + A2 * 2 + A1 * 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 < 109)
 

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
30 1001 105 100
 

Sample Output
Case #1: 1Case #2: 2Case #3: 13
 

Source
2013 ACM/ICPC Asia Regional Chengdu Online

题意:

  我们定义十进制数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,求出0~b有多少个不大于f(a)的数。


分析:

dp[i][j]表示i位值<=j 的总数

#include<bits/stdc++.h>using namespace std;int dp[20][200000], bit[20];int A, B;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 lim = flag ? bit[pos] : 9;    for(int i = 0; i <= lim; i++)        ans += dfs(pos-1, num-i*(1<<pos), flag&&i==lim);    if(!flag)        dp[pos][num] = ans;    return ans;}int F(int x){    int ret = 0, len = 0;    while(x)    {        ret += (x%10)*(1<<len);        len++;        x /= 10;    }    return ret;}int calc(){    int len = 0;    while(B)    {        bit[len++] = B % 10;        B /= 10;    }    return dfs(len-1, F(A), true);}int main(){    int t;    scanf("%d", &t);    memset(dp, -1, sizeof(dp));    for(int kase = 1; kase <= t; kase++)    {        scanf("%d%d", &A, &B);        printf("Case #%d: %d\n", kase, calc());    }    return 0;}





原创粉丝点击