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\n",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

posted @ 2016-06-19 21:32  晴歌。  阅读(...)  评论(... 编辑 收藏