SPOJ BALNUM Balanced Numbers 状压+数位DP

一开始想了一个用二进制状压的方法,发现空间需要的太大,光光memset都要超时 = = 其实不用每次都memset

也可以用三进制,一开始直接打表出所有的状态转移就好

#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <climits>
#include <string>
#include <iostream>
#include <map>
#include <cstdlib>
#include <list>
#include <set>
#include <queue>
#include <stack>

using namespace std;

typedef unsigned long long ULL;
typedef long long LL;
const ULL INF = ~0ULL;
const int maxn = 20;
const int maxstate = 59049;
int lim[maxn],len = 0;
int ccon[maxstate][10];
bool ok[maxstate];

void getlim(ULL num) {
    memset(lim,0,sizeof(lim));
    len = 0;
    while(num) {
        lim[len++] = num % 10;
        num /= 10;
    }
}

ULL f[maxn][maxstate];

int tmp[10];
inline int con(int ns,int pos) {
    for(int i = 9;i >= 0;i--) {
        tmp[i] = ns % 3; ns /= 3;
    }
    if(tmp[pos] == 0) tmp[pos] = 1;
    else if(tmp[pos] == 1) tmp[pos] = 2;
    else tmp[pos] = 1;
    int ret = 0;
    for(int i = 0;i <= 9;i++) {
        ret *= 3; ret += tmp[i]; }
    return ret;
}

inline bool check(int st) {
    for(int i = 9;i >= 0;i--)  {
        tmp[i] = st % 3; st /= 3;
    }
    for(int i = 0;i <= 9;i++) if(tmp[i]) {
        if((i % 2) == (tmp[i] % 2)) return false;
    }
    return true;
}

ULL dfs(int now,int state,int first,int bound) {
    if(now == 0) {
        return ok[state];
    }
    ULL &note = f[now][state];
    if(!bound && first && note != INF) return note;
    int m = bound ? lim[now - 1] : 9;
    ULL ret = 0;
    for(int i = 0;i <= m;i++) {
        if(first || i) {
            ret += dfs(now -  1,ccon[state][i],1,i == m && bound);
        } else {
            ret += dfs(now - 1,state,0,i == m && bound);
        }
    }
    if(!bound && first) note = ret;
    return ret;
}

ULL solve(ULL num) {
    getlim(num);
    return dfs(len,0,0,1);
}

void init() {
    for(int i = 0;i < maxstate;i++) {
        for(int j = 0;j < 10;j++) {
            ccon[i][j] = con(i,j);
        }
        ok[i] = check(i);
    }
}

int main() {
    int T; cin >> T;
    ULL a,b;
    init();
    memset(f,0xff,sizeof(f));
    while(T--) {
        cin >> a >> b;
        cout << solve(b) - solve(a - 1) << endl;
    }
    return 0;
}

  

SPOJ BALNUM Balanced Numbers 状压+数位DP

时间: 2024-10-18 16:06:40

SPOJ BALNUM Balanced Numbers 状压+数位DP的相关文章

SPOJ BALNUM Balanced Numbers(数位dp,状态压缩)

BALNUM - Balanced Numbers no tags 题目链接 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)   

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

SPOJ - BALNUM - Balanced Numbers(数位DP)

链接: https://vjudge.net/problem/SPOJ-BALNUM 题意: 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)

lightoj-1021 - Painful Bases(状压+数位dp)

1021 - Painful Bases PDF (English) Statistics ForumTime Limit: 2 second(s) Memory Limit: 32 MBAs you know that sometimes base conversion is a painful task. But still there are interesting facts in bases. For convenience let's assume that we are deali

Topcoder SRM655 DIV2 950 NineEasy 状压 + 数位 dp

题意:要你构造一个n位的数子 ,给你m(1-5)个询问,每一次询问取一些位数的数组成一个新数且这个数 %9 ==  0 , 问你要满足这m个询问的数字有多少个(允许前缀0). 解题思路:把每一种情况状压,得到一个最多  9x9x9x9x9 的情况,然后根据 每个数的询问决定状态转移方程. 解题代码: 1 // BEGIN CUT HERE 2 /* 3 4 */ 5 // END CUT HERE 6 #line 7 "NineEasy.cpp" 7 #include <cstd

SPOJ BALNUM Balanced Numbers 平衡数(数位DP,状压)

题意: 平衡树定义为“一个整数的某个数位若是奇数,则该奇数必定出现偶数次:偶数位则必须出现奇数次”,比如 222,数位为偶数2,共出现3次,是奇数次,所以合法.给一个区间[L,R],问有多少个平衡数? 思路: 这题比较好解决,只有前导零问题需要解决.如果枚举到011,那么其前导零(偶数)出现了1次而已,而此数11却是平衡数,所以不允许前导零的出现! 由于dfs时必定会枚举到前导零,否则位数较少的那些统计不到.状态需要3维or2维也行,3维的比较容易处理,用一维表示数位出现次数,另一维表示数位是否

[SPOJ BALNUM] Balanced Numbers

dp[dep][ex][sta]表示长度为dep的,前面出现过的数的集合为ex,不满足要求的数字的集合为sta的满足要求的数的个数 1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 ll dp[20][1024][1024]; 5 int dig[20],tmp; 6 ll dfs(int dep,int ex,int sta,int zero,int flag){ 7 if(!dep)retu

SPOJ MYQ10 10649. Mirror Number (数位dp)

SPOJ MYQ10 10649. Mirror Number (数位dp) ACM 题目地址:SPOJ MYQ10 Mirror Number 题意: 求[a,b]中镜像回文的个数. 0 <= a<=b <= 10^44 分析: 看到题目和数据范围就知道是数位dp了. 很明显镜像回文只有0,1,8,跟回文的一题一样,在dfs的时候得开个辅助数组记录前面已经选择的数字. 注意还得去掉前导0. 代码: /* * Author: illuz <iilluzen[at]gmail.com

BALNUM - Balanced Numbers

BALNUM - Balanced Numbers Time limit:123 ms Memory limit:1572864 kB 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