1026: [SCOI2009]windy数 - BZOJ

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

【数据规模和约定】
20%的数据,满足 1 <= A <= B <= 1000000 。
100%的数据,满足 1 <= A <= B <= 2000000000 。

 

dp,f[i,j]表示有i位,最高位是j的windy数有多少(当然,这里有前导0)

我们只要会算1到x有多少windy数,就可以通过减法得到a到b的windy数有多少个

我们先不考虑每一位的限制,最后减掉不合法的就行了

考虑怎么才不合法,就是windy数比x大

即高位全部一样,第i位大与x的第i位,就减去它的方案数,但是要注意,高位一样可能就不是windy数了,所以从高往低做,不可能是windy数的时候就退出

实在不懂可以看代码

 1 var

 2     f:array[0..10,0..10]of int64;

 3     i,j,k:longint;

 4     a,b:int64;

 5  

 6 function fx(x:int64):int64;

 7 var

 8     i,j,k:longint;

 9     s:array[0..11]of longint;

10 begin

11     i:=0;

12     while x>0 do

13       begin

14         inc(i);

15         s[i]:=x mod 10;

16         x:=x div 10;

17       end;

18     fx:=0;

19     for j:=1 to i do

20       for k:=1 to 9 do

21         inc(fx,f[j,k]);

22     s[i+1]:=12;

23     for j:=s[i]+1 to 9 do

24       dec(fx,f[i,j]);

25     while (i>1) and (abs(s[i]-s[i+1])>1) do

26       begin

27         for j:=s[i-1]+1 to 9 do

28           if abs(s[i]-j)>1 then dec(fx,f[i-1,j]);

29         dec(i);

30       end;

31 end;

32  

33 begin

34     read(a,b);

35     for i:=0 to 9 do

36       f[1,i]:=1;

37     for i:=2 to 10 do

38       for j:=0 to 9 do

39         for k:=0 to 9 do

40           if abs(j-k)>1 then inc(f[i,j],f[i-1,k]);

41     write(fx(b)-fx(a-1));

42 end.
View Code

 

你可能感兴趣的:(ZOJ)