HDU 4734 数位DP

来源:互联网 发布:内存优化级别禁用好吗 编辑:程序博客网 时间:2024/06/05 01:08

F(x)

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


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. Thet 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

思路:先计算出F(A),然后一直数位DP记录状态减到小于0为止。

#include <bits/stdc++.h>#define LL long longusing namespace std;const int AX = 2e4+666;LL dp[25][AX];int a[25];int fa ;int dfs( int pos , int sta , bool limit ){if( pos == -1 ) return sta >= 0 ;if( sta < 0 ) return 0 ;if( !limit && dp[pos][sta] != -1 ) return dp[pos][sta];int up = limit ? a[pos] : 9 ;int ans = 0;for( int i = 0 ; i <= up ; i++ ){int stanow = sta - ( 1 << pos ) * i ;ans += dfs( pos-1 , stanow , limit && up == i );} if( !limit ) dp[pos][sta] = ans ;return ans ;}int solve( int x ){int tot = 0 ;while( x ){a[tot++] = x % 10 ;x /= 10 ;}return dfs( tot - 1 , fa , true );}void F( int x ){int i = 0 ;fa = 0 ;while( x ){fa += ( 1 << i ) * ( x % 10 );x /= 10;i ++ ;}}int main(){int T;cin >> T;int a , b;memset(dp,-1,sizeof(dp));int cas = 0;while( T -- ){cin >> a >> b ;F(a);printf("Case #%d: ",++cas);cout << solve(b) << endl;}return 0;}