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;
}