套路题,在数字上面进行dfs,要点是剪枝(记忆的状态不同,效果大不一样)
---------------------------------------------------
http://acm.hdu.edu.cn/showproblem.php?pid=2089
1 #include <iostream> 2 #include <string.h> 3 using namespace std; 4 int n, m, num[20], dp[20][2]; 5 int d(int pos, int pre, int st, bool limi){ 6 if(pos == -1) return 1; 7 if(!limi && dp[pos][st] != -1) return dp[pos][st]; 8 int up = limi ? num[pos] : 9; 9 int sum = 0; 10 for(int i = 0; i <= up; ++i){ 11 if(pre == 6 && i == 2) continue; 12 if(i == 4) continue; 13 sum += d(pos-1, i, i == 6, limi && i == up); 14 } 15 if(!limi) dp[pos][st] = sum; 16 return sum; 17 } 18 int f(int x){ 19 int pos = 0; 20 while(x){ 21 num[pos++] = x%10; 22 x /= 10; 23 } 24 num[pos] = 0; 25 return d(pos-1, 1, 0, true); 26 } 27 int main(){ 28 memset(dp, -1, sizeof(dp)); 29 while(~scanf("%d%d", &n, &m)){ 30 if(n == 0 && m == 0) break; 31 printf("%d ", f(m) - f(n-1)); 32 } 33 return 0; 34 }
---------------------------------------------------
http://acm.hdu.edu.cn/showproblem.php?pid=6156
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 using namespace std; 5 typedef long long ll; 6 ll dp[40][40][40][2], L, R; 7 int num[40],temp[40], l, r; 8 ll dfs(int bas, int start,int cur,bool state,bool fp){ 9 if(cur<0) 10 return state; 11 if(!fp&&dp[bas][start][cur][state]!=-1) 12 return dp[bas][start][cur][state]; 13 int fpmax = fp ? num[cur] : (bas-1); 14 ll ret = 0; 15 for(int i = 0; i <= fpmax; i++){ 16 temp[cur] = i; 17 if(start == cur && i == 0) 18 ret += dfs(bas, start-1, cur-1, state, fp && i==fpmax); 19 else if(state && cur < (start+1)/2) 20 ret += dfs(bas, start, cur-1, temp[start-cur]==i, fp&&i==fpmax); 21 else 22 ret+=dfs(bas, start, cur-1, state, fp&&i==fpmax); 23 } 24 if(!fp) 25 dp[bas][start][cur][state] = ret; 26 return ret; 27 } 28 ll f(ll n){ 29 ll sum = 0, nn = n; 30 for(int i = l; i <= r; ++i){ 31 int len=0; 32 sum += nn; 33 n = nn; 34 while(n){ 35 num[len++] = n%i; 36 n /= i; 37 } 38 num[len]=0; 39 sum += dfs(i, len-1, len-1, 1, 1)*(i-1); 40 } 41 return sum; 42 } 43 int main(){ 44 int T; 45 scanf("%d", &T); 46 int res = 1; 47 memset(dp,-1,sizeof(dp)); 48 while(T--){ 49 scanf("%lld%lld%d%d", &L, &R, &l, &r); 50 printf("Case #%d: %lld ", res++, f(R)-f(L-1)); 51 } 52 return 0; 53 }
-------------------------------------------------
http://codeforces.com/problemset/problem/855/E
1 #include <iostream> 2 #include <string.h> 3 using namespace std; 4 #define ll long long 5 ll n, m, num[66], dp[66][66][1025]; 6 ll d(ll cnt, ll sum, ll pos, ll st, bool pre, bool limi) { 7 if(pos == -1) return sum == 0; 8 if(!pre && !limi && dp[cnt][pos][sum] != -1) return dp[cnt][pos][sum]; 9 ll up = limi ? num[pos] : cnt - 1; 10 ll summ = 0; 11 for(ll i = 0; i <= up; ++i) { 12 ll M; 13 if(pre && i == 0) M = sum; 14 else M = sum ^ (1LL << i); 15 summ += d(cnt, M, pos - 1, i, pre && i == 0, limi && i == up); 16 } 17 if(!pre && !limi) dp[cnt][pos][sum] = summ; 18 return summ; 19 } 20 ll f(ll cnt, ll x) { 21 ll pos = 0; 22 while(x) { 23 num[pos++] = x % cnt; 24 x /= cnt; 25 } 26 num[pos] = 0; 27 return d(cnt, 0, pos - 1, 0, true, true); 28 } 29 int main() { 30 memset(dp, -1, sizeof(dp)); 31 ll t, x; 32 ll l, r; 33 scanf("%lld", &t); 34 while(t--) { 35 scanf("%lld%lld%lld", &x, &l, &r); 36 printf("%lld ", f(x, r) - f(x, l - 1)); 37 } 38 return 0; 39 }
--------------------------------------------------
-----------------------------------------------------
-------------------------------------------------------
只有不断学习才能进步!