zoukankan      html  css  js  c++  java
  • BZOJ_1026_[SCOI2009]_windy数_(数位dp)

    描述


    http://www.lydsy.com/JudgeOnline/problem.php?id=1026

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

    分析


    我们用(dp[i][j])表示以(j)开头的(i)为数中windy数一共有多少.

    然后用(solve(x))求出([1,x])内的windy数一共有多少,步骤如下:

    1.将(x)一位一位拆开,共(cnt)位,第(i)位为(num[i]).

    2.统计以(1,2,3,...,9)开头的(i)位数中共有多少windy数,其中(i<cnt).

    3.对于(cnt)位数,显然我们是不能把(dp[cnt][num[cnt])加进去的.比如(x=5786),以(5)开头的(4)位数没有完全包含,所以只能从(dp[cnt][1])计算到(dp[cnt][num[cnt]-1]),然后对于第(cnt)位为(num[cnt])的,就到(cnt-1)位去计算.(相当于数钱,一共5786,数到4999,不能直接数5999,对于>=5000的,要从百位开始数了).

    4.依次往后退,但是注意,当(num[i])与(num[i+1])相差不到(2)的话,对于第(i)位是(num[i])的情况就不需要考虑了,也就不用继续下去了.

    5.由于第(cnt)位不能取(0),而只有最后一位可以去(num[i]),比较特殊,所以需要单独处理,可以特判一位数的情况,确保至少有最高位和最低位两个不同的位.

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 
     4 typedef long long ll;
     5 int num[11];
     6 ll dp[11][11];
     7 ll a,b;
     8 inline ll read(ll &x){ x=0;ll k=-1;char c;for(c=getchar();c<'0'||c>'9';c=getchar())if(c=='-')k=-1;for(;c>='0'&&c<='9';c=getchar())x=x*10+c-'0';return x*k; }
     9 ll solve(int x){
    10     if(x<10) return x;
    11     ll ans=0; int cnt=0;
    12     while(x) num[++cnt]=x%10, x/=10;
    13     for(int i=1;i<cnt;i++) ans+=dp[i][10]-dp[i][0];
    14     for(int i=1;i<num[cnt];i++) ans+=dp[cnt][i];
    15     for(int i=cnt-1;i;i--){
    16         for(int j=0;j<num[i];j++)if(abs(num[i+1]-j)>1)
    17         ans+=dp[i][j];
    18         if(i==1&&abs(num[i+1]-num[i])>1) ans++;
    19         if(abs(num[i+1]-num[i])<=1) break;
    20     }
    21     return ans;
    22 }
    23 int main(){
    24     read(a); read(b);
    25     for(int i=0;i<10;i++) dp[1][i]=1;
    26     dp[1][10]=10;
    27     for(int i=2;i<=10;i++)for(int j=0;j<10;j++){
    28         for(int k=0;k<10;k++)if(abs(j-k)>1) 
    29             dp[i][j]+=dp[i-1][k];
    30         dp[i][10]+=dp[i][j];
    31     }
    32     printf("%lld
    ",solve(b)-solve(a-1));
    33 }
    View Code

    1026: [SCOI2009]windy数

    Time Limit: 1 Sec  Memory Limit: 162 MB
    Submit: 5441  Solved: 2450
    [Submit][Status][Discuss]

    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 。

    Source

  • 相关阅读:
    Building Java Projects with Gradle
    Vert.x简介
    Spring及Spring Boot 国内快速开发框架
    dip vs di vs ioc
    Tools (StExBar vs Cmder)which can switch to command line window on context menu in windows OS
    SSO的定义、原理、组件及应用
    ModSecurity is an open source, cross-platform web application firewall (WAF) module.
    TDD中测试替身学习总结
    Spring事务银行转账示例
    台式机(华硕主板)前面板音频接口(耳机和麦克风)均无声的解决办法
  • 原文地址:https://www.cnblogs.com/Sunnie69/p/5598873.html
Copyright © 2011-2022 走看看