描述
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 }
1026: [SCOI2009]windy数
Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 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 。