其他分享
首页 > 其他分享> > 【数位DP】Windy数

【数位DP】Windy数

作者:互联网

【题目链接】

Windy数

【题目描述】

不含前导零且相邻两个数字之差至少为 2 的正整数被称为 windy 数。在 a 和 b 之间,包括 a 和 b ,总共有多少个 windy 数?

【输入】

输入只有一行两个整数,分别表示 a 和 b。1≤a,b≤2 x 109

【输出】

输出一行一个整数表示答案。

【输入样例】

  1 10 【输出样例】   9   与不降数一样,按位分情况讨论的,将数num划分为anan-1...a2a1,从最高位开始到低位,划分为0~ai-1与ai,如果第i位上填的是0~ai-1,那么后面的所有位数都可以填0~9,如果第i位是ai,那么就继续往下讨论下一位,通过这种划分方式,可以保证我们枚举的数不超过num。 此外需要结合前缀和的思想,即求区间[a,b]的windy数个数可转化为求count(b) - count(a - 1)的值。 windy数与不降数除了性质不同外,最大区别就在于windy数不含前导零,而不降数存在前导零并不影响其性质的判定。 举例:352   由于不含前导零,故首位不可从0开始枚举,而是枚举1XX、2XX,30X、31X、32X、33X、34X,350、351、352;而且因为前导零的关系,枚举的时候就无法枚举仅有2位、1位的情况,因此小于n位的情况需要单独统计并累加。   预处理与不降数类似:
1 for(int i = 0;i <= 9;++i)
2     f[1][i] = 1;
3 for(int i = 2;i < N;++i)
4     for(int j = 0;j <= 9;++j)
5         for(int k = 0;k <= 9;++k)
6             if(abs(j - k) >= 2) 
7                 f[i][j] += f[i - 1][k];

 

之后只需要把数字拆分出来,分情况枚举,并且不要忘记统计小于n位的情况即可。

 1 #include <iostream>
 2 #include <algorithm>
 3 using namespace std;
 4 const int N = 12;
 5 int f[N][N];
 6 int num[N];
 7 
 8 int count(int n)
 9 {
10     if(n == 0)
11         return 0;
12     int cnt = 0;
13     while(n)
14     {
15         num[++cnt] = n%10;
16         n /= 10;
17     }
18     int res = 0;
19     int now = 0,last = -2;
20     for(int i = cnt;i > 0;--i)
21     {
22         now = num[i];
23         for(int j = (i == cnt);j < now;++j)
24         {
25             if(abs(j - last) >= 2)
26                 res += f[i][j];
27         }
28         if(abs(last - now) < 2)
29             break;
30         last = now;
31         if(i == 1)
32             res++;
33     }
34     for(int i = 1;i < cnt;++i)  //统计小于n位的情况,且不要忘记小于n位的情况中,首位也是从1开始枚举,而不是0
35         for(int j = 1;j <= 9;++j)
36             res+= f[i][j];
37     return res;
38 }
39 
40 int main()
41 {
42     for(int i = 0;i <= 9;++i)
43         f[1][i] = 1;
44     for(int i = 2;i < N;++i)
45         for(int j = 0;j <= 9;++j)
46             for(int k = 0;k <= 9;++k)
47                 if(abs(j - k) >= 2)
48                     f[i][j] += f[i - 1][k];
49     int n,m;
50     cin >> n >> m;
51     cout << count(m) - count(n - 1) << endl; 
52     return 0;
53 } 

 

标签:cnt,int,Windy,windy,num,枚举,now,DP,数位
来源: https://www.cnblogs.com/fengshi99/p/15408542.html