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 }
时间: 2024-11-20 02:46:22

spoj 10606 Balanced Numbers 数位dp的相关文章

SPOJ BALNUM Balanced Numbers(数位dp)

Balanced Numbers Time Limit:123MS     Memory Limit:1572864KB     64bit IO Format:%lld & %llu Submit Status Practice SPOJ BALNUM Description Balanced numbers have been used by mathematicians for centuries. A positive integer is considered a balanced n

Balanced Numbers数位dp

三进制搞下, 0  表示没出现过,  第i位为1 表示 i出现了奇数次,  2表示i 出现了偶数次. #include <cstdio> #include <cstring> #include <algorithm> #include <climits> #include <string> #include <iostream> #include <map> #include <cstdlib> #includ

[数位dp] spoj 10606 Balanced Numbers

题意: 对于一个数的每个位上的数. 对于每个奇数,如果出现必须出现偶数次. 对于每个偶数,如果出现必须出现奇数次. 思路: 用三进制存储每个数出现的状态,0没出现,1出现奇数次,2出现偶数次. 然后其他和普通数位dp就一样了. 代码: #include"cstdlib" #include"cstdio" #include"cstring" #include"cmath" #include"queue" #i

spoj Balanced Numbers(数位dp)

一个数字是Balanced Numbers,当且仅当组成这个数字的数,奇数出现偶数次,偶数出现奇数次 一下子就相到了三进制状压,数组开小了,一直wa,都不报re, 使用记忆化搜索,dp[i][s] 表示长度为i,状态为s,时,满足条件的balance number的个数 #include <stdio.h> #include <string.h> #include <stdlib.h> #include <algorithm> #include <io

SPOJ10606 BALNUM - Balanced Numbers(数位DP+状压)

Balanced numbers have been used by mathematicians for centuries. A positive integer is considered a balanced number if: 1)      Every even digit appears an odd number of times in its decimal representation 2)      Every odd digit appears an even numb

SPOJ BALNUM Balanced Numbers 状压+数位DP

一开始想了一个用二进制状压的方法,发现空间需要的太大,光光memset都要超时 = = 其实不用每次都memset 也可以用三进制,一开始直接打表出所有的状态转移就好 #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <climits> #include <string> #include <iostream&g

SPOJ MYQ10 Mirror Number 数位dp&#39;

题目链接:点击打开链接 MYQ10 - Mirror Number A number is called a Mirror number if on lateral inversion, it gives the same number i.e it looks the same in a mirror. For example 101 is a mirror number while 100 is not. Given two numbers a and b, find the number

cf55dBeautiful numbers数位dp

想到 最小公倍数 其余的就好搞了 ,可是没想到 #include <cstdio> #include <cstring> #include <algorithm> #include <climits> #include <string> #include <iostream> #include <map> #include <cstdlib> #include <list> #include <

[Codefoces 401D]Roman and Numbers 数位dp

http://codeforces.com/problemset/problem/401/D 题目大意:给定一个数字n,将n的每一位数字重新排列,求在这些排列数之中可以被n整除的方法数. 解题思路: 暴力超时-- 大多数人的写法是进行位压缩,不过那样的话需要2^18*100 的空间,效率比较低,重复状态数较多,处理起来也不方便,这一题是给出了512M的空间.但是如果空间再小一倍,前者的方法就无能为力了. 发现有一种对于数位dp来说比较好的状态压缩方式,直接根据数码x出现的次数进行状态压缩.比如说