2017 百度之星复赛题解 01、03、05

01、

  有个易错点,我卡了好久,就是 1(012)#(1) 答案是1012,我刚开始把012的前导0去掉了。。。

03、

  原题

05、

  数位DP,记忆化搜索

  dp[ p ][ q ][ limit ][ ceng ]:表示前一位是 p,前面处于递增(递减)状态q,当前位上限是多少limit,还有多少位ceng .

  根据不同情况递归即可,可以先不写记忆化,先写暴力的,最后加上记忆化。

  

 1 #include<stdio.h>
 2 #include<string.h>
 3 #define Mod 1000000007
 4 #define LL long long
 5 LL dp[105][11][11][2];
 6 
 7 LL dfs(int p, int q, int limit, int ceng){
 8     if(ceng==0){
 9         return 1;
10     }
11     if(dp[ceng][p+1][limit][q]!=-1) return dp[ceng][p+1][limit][q];
12 
13     LL ret = 0;
14     for(int i=0; i<limit; i++){
15         if(q==0){  // 递减
16             if(p==-1 || i <= p) {
17                 if(p==-1 && i==0){
18                     ret += dfs(-1, 0, 10, ceng-1);
19                 } else
20                     ret += dfs(i, 0, 10, ceng-1);
21             } else {
22                 ret += dfs(i, 1, 10, ceng-1);
23             }
24         } else {
25             if(i < p) continue;
26             ret += dfs(i, 1, 10, ceng-1);
27         }
28         ret %= Mod;
29     }
30 
31     dp[ceng][p+1][limit][q]=ret;
32     return ret;
33 }
34 
35 int main(){
36     memset(dp, -1, sizeof(dp));
37     char n[105];
38     int t;
39     scanf("%d", &t);
40     while(t--){
41         scanf("%s", &n);
42         LL ans = 0;
43         int len = strlen(n);
44         int u = 0;
45         for(int i=0; i<len; i++){
46             int limit = n[i]-'0';
47             int p = i==0?-1:n[i-1]-'0';
48 
49             if(u==2) break;
50 
51             ans += dfs(p, u, limit, len-i);
52             ans %= Mod;
53 
54             if(u==0){
55                 if(i!=0 && limit>p){
56                     u=1;
57                 }
58             } else if(u==1){
59                 if(limit<p){
60                     u=2;
61                 }
62             }
63         }
64         printf("%I64d\n", ( (ans - 1 + (u==2?0:1) ) % Mod + Mod ) % Mod );
65     }
66     return 0;
67 }
posted @ 2017-08-18 17:22  hchlqlz  阅读(317)  评论(0编辑  收藏  举报