hdu 4734 F(x) 數位DP裸

Description

For a decimal number x with n digits (A nA n-1A n-2 … A 2A 1), 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


這道題是說要求在0到B裏有多少個數的F值小於等於F(A),然後我們可以發現這題可以數位DP做,F值的定義是一個數的這一位乘以這一位的2次方
舉個例子
1234 = 4 * 1 + 3 * 2 + 2 * 4 + 1 * 8

借這道題寫一下數位DP的模板的套路
dfs函數裏面傳參
dfs( int len, int ... ,int lead, int limit )

有些題會有其他參數,有些題需要傳lead,表示是否有前導0,limit通常表示這一位有沒有限制,如果有限制的話就應該是這一位的上限,如果沒有限制的話就是0-9

在函數裏面我們通常是先設計返回的情況,比如len爲-1的時候返回這個點是否滿足,滿足爲1,不滿足爲0,再比如我們記憶化一個dp[i][j],當這個點沒有limit限制並且沒有前導零限制等各種限制時return這個dp[i][j],否則我們就求一個這一位的up值,表示這一位最大可以取什麼,然後for語句取for一些狀態然後繼續dfs下去,最後在沒有限制的情況下把答案賦值給dp數組,也就是記憶化數組裏面,最後再return即可,通常我們會在solve函數裏面先把數位分解爲我們想要的樣子放到數組裏面,十進制分解,二進制分解等等,放到數組裏面,記錄長度然後再傳入dfs函數中,最後計算得出答案返回到主函數中


這道題其實就是一道裸題,按照上面說的思路來就可以了

#include <bits/stdc++.h>
using namespace std; 
int len, dp[11][ 50000 + 10 ], a[25];

int F( int n ) {
    int tmp = 0, BASE = 1;
    while( n ) {
        tmp += n % 10 * BASE;
        BASE *= 2;
        n /= 10;
    }
    return tmp;
}

int dfs( int pos, int ans, int flag ) {
    if( pos < 0 ) return ans >= 0;
    if( ans < 0 ) return 0;
    int sum = 0;
    if( !flag && dp[pos][ans] != -1 ) return dp[pos][ans];
    int up = flag ? a[pos] : 9;
    for( register int i = 0; i <= up; i++ ) sum += dfs( pos - 1, ans - i * ( 1 << pos ), flag && i == up ); 
    if( !flag ) dp[pos][ans] = sum;
    return sum; 
}

int solve( int A, int B ) {
    len = 0;
    while(B) {
        a[len++] = B % 10;
        B /= 10;
    }
    return dfs( len - 1, F(A), 1 );
}

int main( ) { int T, A, B;
    scanf( "%d", &T );
    memset( dp, -1, sizeof(dp) );
    for( register int Emmmm = 1; Emmmm <= T; Emmmm++ ) {
        scanf( "%d%d", &A, &B );
        printf("Case #%d: %d\n", Emmmm, solve( A, B ) );
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章