首页 > 代码库 > 2017广东工业大学程序设计竞赛决赛 G 等凹数字

2017广东工业大学程序设计竞赛决赛 G 等凹数字

题意:

Description

定义一种数字称为等凹数字,即从高位到地位,每一位的数字先非递增再非递减,不能全部数字一样,且该数是一个回文数,即从左读到右与从右读到左是一样的,仅形成一个等凹峰,如5432123455544334455是合法的等凹数字,543212346123321,111111不是等凹数字。现在问你[L,R]中有多少等凹数字呢?

Input

第一行一个整数T,表示数据的组数。

接下来T行每行俩个数字L和R,(1<=L<=R<=1e18)

Output

 输出一个整数,代表[L,R]中有多少等凹数字

Sample Input

2 1 100 101 200

Sample Output

0 1

HINT

 小于等于2位的数字无凹峰

思路:

数位dp,要记录的状态为剩下的数位,等凹数的长度,前缀的最后一个数字,前缀是否上升过,前缀是否下降过,前缀是否是回文,前缀是否为0。

在判断是否是回文的时候还要用一个数组记录前缀。

实现:

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 using namespace std;
 5 typedef long long ll;
 6 
 7 int num[20], buf[20], n, t;
 8 int dp[20][20][10][2][2][2];
 9 ll l, r;
10 
11 int dfs(int now, int len, int last, bool up, bool down, bool isP, bool lz, bool flag)
12 {
13     if (now == 0)
14     {
15         return up && down && isP;
16     }
17     if (!flag && dp[now][len][last][up][down][isP] != -1)
18         return dp[now][len][last][up][down][isP];
19     int res = 0;
20     int u = flag ? num[now] : 9;
21     for (int i = 0; i <= u; i++)
22     {
23         buf[now] = i;
24         if (lz)
25             res += dfs(now - 1, len - (i == 0), i, up, down, 
26                        isP, i == 0, flag && i == u);
27         else if (i == last)
28         {
29             if (isP && now <= len / 2)
30                 res += dfs(now - 1, len, i, up, down, 
31                            i == buf[len + 1 - now], false, flag && i == u);
32             else
33                 res += dfs(now - 1, len, i, up, down, 
34                            isP, false, flag && i == u);
35         }
36         else if (i < last)
37         {
38             if (up)
39                 continue;
40             if (isP && now <= len / 2)
41                 res += dfs(now - 1, len, i, false, true, 
42                            i == buf[len + 1 - now], false, flag && i == u);
43             else
44                 res += dfs(now - 1, len, i, false, true, 
45                            isP, false, flag && i == u);
46         }
47         else
48         {
49             if (!down)
50                 continue;
51             if (isP && now <= len / 2)
52                 res += dfs(now - 1, len, i, true, true, 
53                            i == buf[len + 1 - now], false, flag && i == u);
54             else
55                 res += dfs(now - 1, len, i, true, true, 
56                            isP, false, flag && i == u);
57         }
58     }
59     return flag ? res : dp[now][len][last][up][down][isP] = res;
60 }
61 
62 int query(ll x)
63 {
64     memset(dp, -1, sizeof(dp));
65     n = 0;
66     while (x)
67     {
68         num[++n] = x % 10;
69         x /= 10;
70     }
71     return dfs(n, n, 0, false, false, true, true, true);
72 }
73 
74 int main()
75 {
76     cin >> t;
77     while (t--)
78     {
79         scanf("%lld %lld", &l, &r);
80         printf("%d\n", query(r) - query(l - 1));
81     }
82     return 0;
83 }

 

2017广东工业大学程序设计竞赛决赛 G 等凹数字