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
", calc(r) - calc(l - 1));
    }
    return 0;
}
原文地址:https://www.cnblogs.com/justPassBy/p/4714681.html