zoukankan      html  css  js  c++  java
  • BZOJ 1026 [SCOI2009]windy数

    1026: [SCOI2009]windy数

    Description

    windy定义了一种windy数。不含前导零且相邻两个数字之差至少为2的正整数被称为windy数。 windy想知道,在A和B之间,包括A和B,总共有多少个windy数?

    Input

    包含两个整数,A B。

    Output

    一个整数

    Sample Input

    【样例一】
    1 10
    【样例二】
    25 50

    Sample Output

    【样例一】
    9
    【样例二】
    20

    HINT

    100%的数据,满足 1 <= A <= B <= 2000000000 。


      数位DP,统计类问题。上下界均在int范围内,故不必用long long(这样的判断是很有必要的)。

      包括A,B。我们通常可以方便算出1~n-1的范围内符合条件的总数。所以,只需要1~(A+1)-1减去1~B-1即可。

      DP方程很好写,但统计确实需要分段。本人最开始想少做些事情,但JIJI了(否则极复杂),也算是刷新了对数位DP的理解。

    • 1~9,10~99,100~999,1000~9999……(先把位数为1至cnt-1计入)
    • 100..0~(x-1)99..9(确定最高位 )
    • x00..0~x(y-1)9..9,xy0..0~xy(z-1)9..9,……,(高位到低位,如果高位已经出现非法,直接退出)
     1 /**************************************************************
     2     Problem: 1026
     3     User: Doggu
     4     Language: C++
     5     Result: Accepted
     6     Time:0 ms
     7     Memory:820 kb
     8 ****************************************************************/
     9  
    10 #include <cstdio>
    11 const int N = 15;
    12 int a, b, f[N][10], ans;
    13 int abs(int a) {return a>0?a:-a;}
    14 int DP(int k,int i) { 
    15     if(f[k][i]) return f[k][i];
    16     if(k==1) return  f[k][i]=1;
    17     for( int j = 0; j <= 9; j++ ) if(abs(i-j)>=2) f[k][i]+=DP(k-1,j);
    18     return f[k][i];
    19 }
    20 void CAL(int num,int delta) {//cal 0~num-1
    21     int digit[N], cnt = 0;
    22     while(num) digit[++cnt]=num%10,num/=10;
    23     for( int bit = 1; bit < cnt; bit++ )  //先把长度为1至cnt-1计入  
    24         for( int i = 1; i < 10; i++ )
    25             ans += delta*DP(bit,i);
    26     for( int i = 1; i < digit[cnt]; i++ )   //确定最高位  
    27         ans += delta*DP(cnt,i);
    28     for( int bit = cnt-1; bit >= 1; bit-- ) {
    29         for( int i = 0; i < digit[bit]; i++ ) if(bit==cnt||abs(i-digit[bit+1])>=2) ans += delta*DP(bit,i);
    30         if(abs(digit[bit]-digit[bit+1])<2) break;//如果高位已经出现非法,直接退出
    31     }
    32 }
    33 int main() {
    34     scanf( "%d%d", &a, &b );
    35     CAL(b+1,+1);
    36     CAL(a,-1);
    37     printf("%d
    ",ans);
    38     return 0;
    数位DP
  • 相关阅读:
    职业规划书
    阿里云mysql安装配置(CentOS 7.3 64)
    在mvc中弹出提示框
    俺的博客开通啦
    sql中计算列小解
    ext的grid 获取页面内容方式
    2条路 代码生成 or 配置 2.1
    ext做列表页面关于查询多行的办法
    .net下开发windows服务的经验
    微软.net下 charting 要注意的事情
  • 原文地址:https://www.cnblogs.com/Doggu/p/bzoj1026.html
Copyright © 2011-2022 走看看