ZOJ 3962 Seven Segment Display(数位DP)

题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3962

题目大意:

有t组数据。 
给你一个n,和8位的十六进制数st,还有一张表格,里面有每一个数字的消耗。

比如"5A8BEF67"的消耗为为5 + 6 + 7 + 5 + 5 + 4 + 6 + 3 = 41。

然后让你求[n,n+st-1]区间的所有的数字的消耗之和。

解题思路:

数位DP,用solve(x)求0~x的总消耗。

lim=0xFFFFFFFF

则可以分两种情况:

①n+st-1>=lim,输出solve((st+n-1)%lim)+solve(lim-1)-solve(st-1)

②n+st-1<lim,输出solve(st+n-1)-solve(st-1)

其实这题可以算是比较明显的数位DP了,写起来也很简单,只是题目有点吓人,所以没敢写。。。

代码

 1 #include<cstdio>
 2 #include<cmath>
 3 #include<cctype>
 4 #include<cstring>
 5 #include<iostream>
 6 #include<algorithm>
 7 #include<vector>
 8 #include<queue>
 9 #include<set>
10 #include<map>
11 #include<stack>
12 #include<string>
13 #define lc(a) (a<<1)
14 #define rc(a) (a<<1|1)
15 #define MID(a,b) ((a+b)>>1)
16 #define fin(name)  freopen(name,"r",stdin)
17 #define fout(name) freopen(name,"w",stdout)
18 #define clr(arr,val) memset(arr,val,sizeof(arr))
19 #define _for(i,start,end) for(int i=start;i<=end;i++)
20 #define FAST_IO ios::sync_with_stdio(false);cin.tie(0);
21 using namespace std;
22 typedef long long LL;
23 const int N=1e2+5;
24 const int INF=0x3f3f3f3f;
25 const LL lim=(1LL<<32);
26 
27 int mp[20]={6,2,5,5,4,5,6,3,7,6,6,5,4,5,5,4};
28 LL top[N],dp[N][N];        //dp[pos][val]其中pos表示数位,val表示当前需要消耗的电路 
29 char str[N];
30 
31 LL dfs(bool limit,int pos,int val){
32     if(pos==-1)    return val;
33     if(!limit&&dp[pos][val]!=-1) return dp[pos][val];
34     int up=limit?top[pos]:15;
35     LL ans=0;
36     for(int i=0;i<=up;i++){
37         ans+=dfs(limit&&i==up,pos-1,val+mp[i]);
38     }
39     if(!limit) dp[pos][val]=ans;
40     return ans;
41 }
42 
43 LL solve(LL x){
44     if(x==-1) return 0;
45     int cnt=-1;
46     while(x){
47         top[++cnt]=x%16;
48         x/=16;
49     }
50     while(cnt<7){
51         top[++cnt]=0;
52     }
53     return dfs(1,cnt,0);
54 }
55 
56 int main(){
57     int t;
58     scanf("%d",&t);
59     memset(dp,-1,sizeof(dp));
60     while(t--){
61         LL n,st;
62         scanf("%lld %llx",&n,&st);
63         LL ans;
64         if(st+n-1>=lim){
65             ans=solve((st+n-1)%lim)+solve(lim-1)-solve(st-1);
66         }
67         else{
68             ans=solve(st+n-1)-solve(st-1);
69         }
70         printf("%lld
",ans);
71     }
72     return 0;
73 }
原文地址:https://www.cnblogs.com/fu3638/p/8955192.html