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 <iostream> #include <queue> #include <stack> #include <vector> #include <map> #include <set> #include <string> #include <math.h> using namespace std; #pragma warning(disable:4996) #pragma comment(linker, "/STACK:1024000000,1024000000") typedef long long LL; const int INF = 1<<30; /* */ int num[30]; LL dp[30][60000]; int getNum(int sta) { int tmp1, tmp2; for (int i = 0; i <= 9; ++i) { tmp1 = i &1; tmp2 = sta % 3; if (tmp1==0 && tmp2==2)//偶数出现了偶数次 return 0; if (tmp1 == 1 && tmp2 == 1)//奇数出现了奇数次 return 0; sta /= 3; } return 1; } int getSta(int x, int sta) { int val = 1; int newSta = sta; for (int i = 0; i < x; ++i) { val *= 3; sta /= 3; } int times = sta % 3; if (times == 0 || times == 1) return newSta + val; else return newSta - val; } LL dfs(int pos, int sta, bool zero, bool flag) { if (pos == 0) return getNum(sta); if (!flag && dp[pos][sta] != -1) return dp[pos][sta]; int end = flag ? num[pos] : 9; LL ans = 0; for (int i = 0; i <= end; ++i) ans += dfs(pos - 1, (zero&&i==0)?0:getSta(i, sta),zero&&i==0 ,flag&&i == end); if (!flag) dp[pos][sta] = ans; return ans; } LL calc(LL n) { int len = 0; while (n) { num[++len] = n % 10; n /= 10; } return dfs(len, 0, true, true); } int main() { memset(dp, -1, sizeof(dp)); int t; LL l, r; scanf("%d", &t); while (t--) { scanf("%lld%lld", &l, &r); printf("%lld\n", calc(r) - calc(l - 1)); } return 0; }