spoj 10606 Balanced Numbers 数位dp

题目链接

一个数称为平衡数, 满足他各个数位里面的数, 奇数出现偶数次, 偶数出现奇数次, 求一个范围内的平衡数个数。

用三进制压缩, 一个数没有出现用0表示, 出现奇数次用1表示, 出现偶数次用2表示, 这样只需要开一个20*60000的数组。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define pb(x) push_back(x)
 4 #define ll long long
 5 #define mk(x, y) make_pair(x, y)
 6 #define lson l, m, rt<<1
 7 #define mem(a) memset(a, 0, sizeof(a))
 8 #define rson m+1, r, rt<<1|1
 9 #define mem1(a) memset(a, -1, sizeof(a))
10 #define mem2(a) memset(a, 0x3f, sizeof(a))
11 #define rep(i, a, n) for(int i = a; i<n; i++)
12 #define ull unsigned long long
13 typedef pair<int, int> pll;
14 const double PI = acos(-1.0);
15 const double eps = 1e-8;
16 const int mod = 1e9+7;
17 const int inf = 1061109567;
18 const int dir[][2] = { {-1, 0}, {1, 0}, {0, -1}, {0, 1} };
19 int digit[20], a[20];
20 ll dp[20][60000];
21 int judge(int num) {
22     int cnt = 0;
23     for(int i = 0; i<10; i++) {
24         a[i] = num%3;
25         num/=3;
26     }
27     for(int i = 0; i<10; i++) {
28         if(i%2==0&&a[i]==2)
29             return 0;
30         if(i%2==1&&a[i]==1)
31             return 0;
32     }
33     return 1;
34 }
35 int cal(int num, int tmp) {
36     int cnt = 0;
37     for(int i = 0; i<10; i++) {
38         a[i] = num%3;
39         num/=3;
40     }
41     a[tmp]++;
42     if(a[tmp]==3)
43         a[tmp]=1;
44     for(int i = 9; i>=0; i--) {
45         num = num*3+a[i];
46     }
47     return num;
48 }
49 ll dfs(int len, int num, int fp, bool first) {
50     if(!len) {
51         return judge(num);
52     }
53     if(!fp&&dp[len][num]!=-1) {
54         return dp[len][num];
55     }
56     ll ret = 0;
57     int maxx = fp?digit[len]:9;
58     for (int i = 0; i<=maxx; i++) {
59         ret += dfs(len-1, (first&&i==0)?0:cal(num, i), fp&&i==maxx, i==0&&first);
60     }
61     if(!fp)
62         return dp[len][num] = ret;
63     return ret;
64 }
65 ll cal(ll n) {
66     int len = 0;
67     while(n) {
68         digit[++len] = n%10;
69         n/=10;
70     }
71     return dfs(len, 0, 1, true);
72 }
73 int main()
74 {
75     mem1(dp);
76     int t;
77     ll a, b;
78     cin>>t;
79     while(t--) {
80         scanf("%lld%lld", &a, &b);    //I64d会超时......
81         printf("%lld\n", cal(b)-cal(a-1));
82     }
83 }

 

posted on 2015-12-12 09:52  yohaha  阅读(151)  评论(0编辑  收藏  举报

导航