题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4734
题目描述: 给出两个数A, B, 求出小于B且F(i)小于F(A)的所有i的个数
解题思路: 典型的数位DP, dfs(int len, int cur, int limit) 表示处理到第len位, F(A)还剩cur, 是否限制的答案
代码:
#include <iostream> #include <cstdio> #include <string> #include <vector> #include <map> #include <cstring> #include <iterator> #include <cmath> #include <algorithm> #include <stack> #include <deque> #include <map> #define lson l, m, rt<<1 #define rson m+1, r, rt<<1|1 typedef long long LL; using namespace std; //const int maxn = 70000+10; int digit[20]; int dp[20][200000]; // digit处理到第i位a还剩n的解决方案 int dfs(int len, int cur, int limit) { if( len == -1 ) return cur >= 0; // 所有都判定完了, 如果cur还>=0就证明还有一种方案 if( cur < 0 ) return 0; if( !limit && dp[len][cur] != -1 ) return dp[len][cur]; int ret = 0; int templimit = limit ? digit[len] : 9; for( int i = 0; i <= templimit; i++ ) {; ret += dfs( len-1, cur-i*(1<<len), limit && i == templimit ); } if( !limit ) dp[len][cur] = ret; return ret; } int F(int A) { int ret = 0; int len = 0; while( A ) { ret += (A % 10) * (1 << len); len++; A /= 10; } return ret; } int fun(int A, int n) { int cnt = 0; while( n ) { digit[cnt++] = n % 10; n /= 10; } return dfs( cnt-1, A, 1 ); } int main() { int t; while( scanf( "%d", &t) == 1 ) { int cases = 0; memset(dp, -1, sizeof(dp)); while( t-- ) { int A, n; scanf( "%d%d", &A, &n ); int ans = fun(F(A), n); printf( "Case #%d: %d\n", ++cases, ans ); } } return 0; }
思考: 倒是没有多大问题, 就是老TLE, 后来把数组改成dp[20][20000]就过了, 不知道为什么, 很迷, 照理来说y应该开到两千就过了的啊