zoukankan      html  css  js  c++  java
  • SPOJ BALNUM Balanced Numbers (数位dp)

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

    题意:找出区间[A, B]内所有奇数字出现次数为偶数,偶数字出现次数为计数的数的个数。

    分析:

      明显的数位dp题,首先,只有3种状态(0:没出现过, 1:数字出现奇数次, 2:数字出现偶数次),所以, 0~9 出现的次数就可以用3进制表示,最大的数就是 310 ,那么我们就可以把1019 哈希到310 内了。其中,我们可以假设:

    (0:30  ,1:31 , 2:32 , .... , 9: 39

      当第一次出现是,就把次数 +1, 否则,奇数变偶数(1-->2),偶数变奇数(2-->1)。因此,每个数字的变化在0~2内,3进制不会有冲突产生。

      设记忆化数组f[20][310], 就是f[i][s] 表示取了前 i 位数字哈希后值为 s 的方法数。

     

     

    代码:

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 
     5 using namespace std;
     6 typedef unsigned long long ull;
     7 const int N = 20;
     8 
     9 ull f[N][60000];
    10 int dg[N];
    11 
    12 int check(int s) {
    13     int nu[10];
    14     for(int i = 0; i < 10; ++i) {
    15         int k = s % 3;
    16         s /= 3;
    17         if(!k) continue;
    18         if((i&1) && (k==1)) return 0;
    19         if(!(i&1) && (k==2)) return 0;
    20     }
    21     return 1;
    22 }
    23 
    24 int new_s(int d, int s) {
    25     int nu[10];
    26     for(int i = 0; i < 10; ++i, s /= 3) nu[i] = s % 3;
    27 
    28     if(nu[d] == 0) nu[d] = 1;
    29     else nu[d] = 3 - nu[d];
    30     for(int i = 9; i > -1; --i) s = s * 3 + nu[i];
    31     return s;
    32 }
    33 
    34 ull dfs(int i, int s, bool flag, bool e) {
    35     if(i == -1) return check(s);
    36     if(!e && ~f[i][s]) return f[i][s];
    37     int res = 0;
    38     int u = e ? dg[i] : 9;
    39     for(int d = 0; d <= u; ++d) {
    40         res += dfs(i-1, (flag==0&&d==0) ? 0 : new_s(d, s), flag||d>0, e&&d==u);
    41     }
    42     return e ? res : f[i][s] = res;
    43 }
    44 
    45 
    46 ull solve(ull x) {
    47     int len = 0;
    48     for( ; x; x /= 10) dg[len++] = x % 10;
    49     return dfs(len-1, 0, 0, 1);
    50 }
    51 
    52 int main()
    53 {
    54     int T;
    55     scanf("%d", &T);
    56     ull a, b;
    57     memset(f, -1, sizeof f);
    58     while(T--) {
    59         scanf("%llu %llu", &a, &b);
    60         printf("%llu
    ", solve(b)-solve(a-1));
    61     }
    62     return 0;
    63 }
    View Code

     

  • 相关阅读:
    Array.of()和Array()区别
    less常用方法
    javascript时间戳转换成yyyy-MM-DD格式
    javascript中标准事件流addEventListener介绍
    javascript中模块化知识总结
    搜索栏简单小案例
    css3伸缩布局中justify-content详解
    css3动画简单案例
    正则表达式的语法
    Beautisoup库
  • 原文地址:https://www.cnblogs.com/Duahanlang/p/5243316.html
Copyright © 2011-2022 走看看