zoukankan      html  css  js  c++  java
  • 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;
    }
    

      

  • 相关阅读:
    42 最大子数组Ⅱ
    笔试之const问题
    笔试中sizeof求字节数的问题
    40 用栈实现队列
    38 搜索二维矩阵Ⅱ
    25.Remove Nth Node From End of List(删除链表的倒数第n个节点)
    29.最小的K个数
    28.数组中出现次数超过一半的数字
    27.字符串的排列
    26.二叉搜索树与双向链表
  • 原文地址:https://www.cnblogs.com/rolight/p/3890351.html
Copyright © 2011-2022 走看看