Time Limit:500MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u
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)
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
回顾很多的“数位DP”问题,它们的终点都是一致的!
#include <cstdio> #include <iostream> #include <cstring> #include <string> using namespace std; int b[10], num[10]; int dp[10][9*((1<<10)-1)]; int dfs(int u, int f, bool limit) { if(u < 1) return 1; if(!limit && dp[u][f] != -1) return dp[u][f]; int maxn = limit ? b[u] : 9; int ret = 0, cur; for(int i=0; i<=maxn; i++) { cur = f - i*(1<<u-1); if(cur > 0) { ret += dfs(u-1, cur, limit && i==maxn); } else if(cur == 0) { ret += 1; } } if(!limit) dp[u][f] = ret; return ret; } int f(int n, int a) { int lenb=0; memset(b, 0, sizeof(b)); while(n) { b[++lenb] = n%10; n /= 10; } return dfs(lenb, a, 1); } int main () { num[0] = 1; for(int i=1; i<10; i++) { num[i] = num[i-1] * 10; } int T, A, B; scanf("%d", &T); memset(dp, -1, sizeof(dp)); for(int kase=1; kase<=T; kase++) { scanf("%d%d", &A, &B); int base = 1, F=0; while(A) { F += base * (A % 10); base <<= 1; A /= 10; } printf("Case #%d: %d\n", kase, f(B, F)); } return 0; }