數位dp-鏡子數
阿新 • • 發佈:2019-02-06
A number is called a Mirror number if on lateral inversion, it gives the same number i.e it looks the same in a mirror. For example 101 is a mirror number while 100 is not.
Given two numbers a and b, find the number of mirror numbers in between them (inclusive of a and b).
Input
First line contains T, number of testcases <= 10^5.
Each testcase is described in a single line containing two numbers a and b.
0 <= a<=b <= 10^44
Output
For each test case print the number of mirror numbers between a and b in a single line.
Example
Input: 3 0 10 10 20 1 4 Output: 3 1 1
程式碼如下:
#include <cstdio> #include <algorithm> #include <cstring> #include <iostream> using namespace std; typedef long long ll; const int maxn = 50; ll dp[maxn][maxn][2]; char num[maxn]; int tmp[maxn]; //cur:當前位數,start:映象迴文判斷的開始地方,flag:是否是映象迴文,limit:邊界判斷 ll dfs(int cur, int start, bool flag, bool limit) { if (cur == -1) return flag; if (!limit && dp[cur][start][flag] != -1) return dp[cur][start][flag]; ll ans = 0; int end = limit?(num[cur]-48):9; for (int i = 0; i <= end; i++) { if (i == 0 || i == 1 || i == 8) { bool st = (cur==start && i == 0); //判斷是否是0情況 bool newFlag = flag; if (flag) { if (!st && cur < (start+1)/2) newFlag = (tmp[start-cur] == i); } tmp[cur] = i; ans += dfs(cur-1, st?start-1:start, newFlag, limit&&(i==end)); } } if (!limit) dp[cur][start][flag] = ans; return ans; } ll cal(char str[]) { int len = strlen(str); for (int i = 0; i < len; i++) num[i] = str[len-1-i]; num[len] = 0; return dfs(len-1, len-1, 1, 1); } int main() { int t; char a[maxn], b[maxn]; scanf("%d", &t); getchar(); memset(dp, -1, sizeof(dp)); while (t--) { scanf("%s %s", a, b); ll ans = cal(b) - cal(a); int len = strlen(a); bool flag = true; for (int i = 0; i < len; i++)//這裡要特別注意,判斷a本身是不是鏡子數。 if ((a[i] != '0' && a[i] != '1' && a[i] != '8') || (a[i] != a[len-1-i])) { flag = false; break; } if (flag) ans++; printf("%lld\n", ans); } return 0; }