题目链接: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 }