zoukankan      html  css  js  c++  java
  • BALNUM

    题目链接:http://www.spoj.com/problems/BALNUM/en/

    题意:问你在[A,B]的闭区间内有几个满足要求的数,要求为每个出现的奇数个数为偶数个,每个出现的偶数个数为奇数个。

    显然dfs很好想到dfs(int len , int even[] , int odd[] , int flag , int first)

    even表示前len位出现偶数的总状态 , odd表示前len位出现奇数的总状态,first表示是否为首位(特判全为0的结果)

    但是这样写dfs dp不好搞,因为dp也要能表示前len位的奇偶出现状况,所以索性直接将dp的第二维保存为状态。

    由于一共有0~9,10个数字,而且总共只有奇偶两种状态,所以直接用3进制来保存状态。

    即dp[len][s],dfs(int len , int s , int flag , int first)

    #include <iostream>
    #include <cstring>
    #include <cstdio>
    using namespace std;
    typedef unsigned long long ull;
    const int M = 6e4;
    ull a , b , dp[20][M];
    int dig[20];
    int check(int x) {
        int num[20];
        for(int i = 0 ; i < 10 ; i++) {
            num[i] = x % 3;
            x /= 3;
        }
        for(int i = 0 ; i < 10 ; i++) {
            if(num[i]) {
                if(i % 2 == 0) {
                    if(num[i] == 2)
                        return 0;
                }
                else {
                    if(num[i] == 1)
                        return 0;
                }
            }
        }
        return 1;
    }
    int getsnew(int s , int x) {
        int num[20];
        for(int i = 0 ; i < 10 ; i++) {
            num[i] = s % 3;
            s /= 3;
        }
        if(num[x] != 0)
            num[x] = 3 - num[x];
        else
            num[x] = 1;
        int sum = 0;
        int power = 1;
        for(int i = 0 ; i < 10 ; i++) {
            sum += num[i] * power;
            power *= 3;
        }
        return sum;
    }
    ull dfs(int len , int s , int flag , int first) {
        if(!len)
            return check(s);
        if(!flag && dp[len][s] != -1)
            return dp[len][s];
        int t = flag ? dig[len] : 9;
        ull sum = 0;
        for(int i = 0 ; i <= t ; i++) {
            if(first) {
                sum += dfs(len - 1 , i == 0 ? 0 : getsnew(s , i) , flag && i == t , first && i == 0);
            }
            else {
                sum += dfs(len - 1 , getsnew(s , i) , flag && i == t , first && i == 0);
            }
        }
        if(!flag)
            dp[len][s] = sum;
        return sum;
    }
    ull Gets(ull x) {
        if(x == 0)
            return 1;
        int len = 0;
        while(x) {
            dig[++len] = x % 10;
            x /= 10;
        }
        return dfs(len , 0 , 1 , 1);
    }
    int main() {
        int t;
        memset(dp , -1 , sizeof(dp));
        scanf("%d" , &t);
        while(t--) {
            scanf("%lld%lld" , &a , &b);
            printf("%lld
    " , Gets(b) - Gets(a - 1));
        }
        return 0;
    }
    
  • 相关阅读:
    Kmp 加深理解 之 poj 3461
    Kmp 模板 之 hdu 1711 Number Sequence
    最大连续子序列和(经典DP) 之 hdu 1231 最大连续子序列
    数学 之 hdu 4710 Balls Rearrangement
    01背包变形 之 hdu 2126 Buy the souvenirs
    逆序数 之 hdu 1394 Minimum Inversion Number
    根据进程文件id查看所有进程信息
    N皇后问题
    17. 电话号码的字母组合
    697. 数组的度
  • 原文地址:https://www.cnblogs.com/TnT2333333/p/6160253.html
Copyright © 2011-2022 走看看