UESTC 1307 windy数(数位DP)

在区间内统计任意两位相差大于二的数的个数。数位dp在推到时候注意最高位要特判一下因为最高位是没有前一位的。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <cmath>
 5 #include <cstdlib>
 6 #include <algorithm>
 7 #define ll long long
 8 #define LEN 100
 9 
10 using namespace std;
11 
12 ll dp[LEN][LEN];
13 
14 inline int abs(int x){return x>0?x:-x;}
15 
16 void init()
17 {
18     memset(dp, 0, sizeof dp);
19     for(int i=0; i<LEN; i++)dp[1][i] = 1;
20     for(int i=2; i<LEN; i++){
21         for(int j=0; j<10; j++){
22             for(int k=0; k<10; k++){
23                 if(abs(j-k)<2)continue;
24                 dp[i][j] += dp[i-1][k];
25             }
26         }
27     }
28 }
29 
30 ll solve(ll x){
31     if(!x)return 0;
32     ll ret = 0;
33     int str[LEN] = {0};
34     int len = 0;
35     while(x){
36         str[++len] = x%10;
37         x/=10;
38     }
39     bool flag = true;
40     for(int i=1; i<len; i++){
41         for(int j=1; j<=9; j++){
42             ret+=dp[i][j];
43         }
44     }
45     for(int i=len; i>=1; i--){
46         for(int j=0; j<str[i]; j++){
47             if(i==len && !j) continue;
48             if(abs(str[i+1]-j)<2 && i!=len)continue;
49             ret += dp[i][j];
50         }
51         if(abs((str[i+1])-(str[i]))<2 && i!=len){
52             flag = false;
53             break;
54         }
55     }
56     if(flag)ret++;
57     return ret;
58 }
59 
60 int main()
61 {
62 //    freopen("in.txt", "r", stdin);
63     ll a, b;
64     init();
65     while(cin >> a >> b){
66         ll ans = solve(b)-solve(a-1);
67         cout << ans << endl;
68     }
69     return 0;
70 }
View Code
奔跑吧!少年!趁着你还年轻
原文地址:https://www.cnblogs.com/shu-xiaohao/p/3453326.html