bzoj1026 [SCOI2009]windy数
1026: [SCOI2009]windy数
Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 4031 Solved: 1803
[Submit][Status][Discuss]
Description
windy定义了一种windy数。不含前导零且相邻两个数字之差至少为2的正整数被称为windy数。 windy想知道,在A和B之间,包括A和B,总共有多少个windy数?
Input
包含两个整数,A B。
Output
一个整数。
Sample Input
【输入样例一】
1 10
【输入样例二】
25 50
1 10
【输入样例二】
25 50
Sample Output
【输出样例一】
9
【输出样例二】
20
9
【输出样例二】
20
HINT
【数据规模和约定】
100%的数据,满足 1 <= A <= B <= 2000000000 。
Source
题意:不解释
解法:提供两种解法
1、打表,每隔10000000w记录一下1-x*10000000有多少windy数,然后没算到的部分暴力算,算过得直接相减得到答案,显然,每次求解最多运算20000000w次,显然不会超时
2、数位dp,先数位dp 1-(a-1)有多少,再dp 1-b有多少,相减即得答案,没什么要注意的,唯一要注意的就是前面全是零的情况
只给出第二种解法
dp[n][m][2] 第一位表示现在是第几位,第二维表示第i 位填数字几,第三位表示目前填满了没有
1 #include <cstdio> 2 #include <cstring> 3 #include <cstdlib> 4 #include <cmath> 5 #include <deque> 6 #include <vector> 7 #include <queue> 8 #include <iostream> 9 #include <algorithm> 10 #include <map> 11 #include <set> 12 #include <ctime> 13 using namespace std; 14 typedef long long LL; 15 typedef double DB; 16 #define For(i, s, t) for(int i = (s); i <= (t); i++) 17 #define Ford(i, s, t) for(int i = (s); i >= (t); i--) 18 #define Rep(i, t) for(int i = (0); i < (t); i++) 19 #define Repn(i, t) for(int i = ((t)-1); i >= (0); i--) 20 #define rep(i, x, t) for(int i = (x); i < (t); i++) 21 #define MIT (2147483647) 22 #define INF (1000000001) 23 #define MLL (1000000000000000001LL) 24 #define sz(x) ((int) (x).size()) 25 #define clr(x, y) memset(x, y, sizeof(x)) 26 #define puf push_front 27 #define pub push_back 28 #define pof pop_front 29 #define pob pop_back 30 #define ft first 31 #define sd second 32 #define mk make_pair 33 inline void SetIO(string Name) { 34 string Input = Name+".in", 35 Output = Name+".out"; 36 freopen(Input.c_str(), "r", stdin), 37 freopen(Output.c_str(), "w", stdout); 38 } 39 40 const int N = 15, M = 10; 41 int A, B; 42 int Arr[N], Dp[N][M][2]; 43 44 inline void Input() { 45 scanf("%d%d", &A, &B); 46 } 47 48 inline int Work(int x) { 49 if(x <= 0) return 0; 50 int Len = 0; 51 for(int t = x; t; t /= 10) Arr[++Len] = t%10; 52 clr(Dp, 0); 53 For(i, 1, Arr[Len]-1) Dp[Len][i][0] = 1; 54 Dp[Len][Arr[Len]][1] = 1; 55 Ford(i, Len-1, 1) { 56 Rep(j, M) { 57 if(Dp[i+1][j][0]) { 58 For(k, 0, j-2) Dp[i][k][0] += Dp[i+1][j][0]; 59 For(k, j+2, 9) Dp[i][k][0] += Dp[i+1][j][0]; 60 } 61 62 if(Dp[i+1][j][1]) { 63 int Cnt = min(Arr[i], j-2); 64 For(k, 0, Cnt) Dp[i][k][k == Arr[i]] += Dp[i+1][j][1]; 65 For(k, j+2, Arr[i]) Dp[i][k][k == Arr[i]] += Dp[i+1][j][1]; 66 } 67 } 68 For(j, 1, 9) Dp[i][j][0]++; 69 } 70 71 int Ret = 0; 72 Rep(i, M) { 73 Ret += Dp[1][i][0]; 74 Ret += Dp[1][i][1]; 75 } 76 return Ret; 77 } 78 79 inline void Solve() { 80 if(A > B) swap(A, B); 81 82 int L = Work(A-1); 83 int R = Work(B); 84 printf("%d\n", R-L); 85 } 86 87 int main() { 88 SetIO("1026"); 89 Input(); 90 Solve(); 91 return 0; 92 }