定义一种数字称为等凹数字,即从高位到地位,每一位的数字先非递增再非递减,不能全部数字一样,且该数是一个回文数,即从左读到右与从右读到左是一样的,仅形成一个等凹峰,如543212345,5544334455是合法的等凹数字,543212346,123321,111111不是等凹数字。现在问你[L,R]中有多少等凹数字呢?
标签:font isp span 数字 数位 using down mil nbsp
题意:
定义一种数字称为等凹数字,即从高位到地位,每一位的数字先非递增再非递减,不能全部数字一样,且该数是一个回文数,即从左读到右与从右读到左是一样的,仅形成一个等凹峰,如543212345,5544334455是合法的等凹数字,543212346,123321,111111不是等凹数字。现在问你[L,R]中有多少等凹数字呢?
第一行一个整数T,表示数据的组数。
接下来T行每行俩个数字L和R,(1<=L<=R<=1e18)
输出一个整数,代表[L,R]中有多少等凹数字
小于等于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 }
标签:font isp span 数字 数位 using down mil nbsp
原文地址:http://www.cnblogs.com/wangyiming/p/6657111.html