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

原文地址:https://www.cnblogs.com/Sunnie69/p/5598873.html