题目链接: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了,写起来也很简单,只是题目有点吓人,所以没敢写。。。
代码
#include<cstdio>
#include<cmath>
#include<cctype>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
#include<set>
#include<map>
#include<stack>
#include<string>
#define lc(a) (a<<1)
#define rc(a) (a<<1|1)
#define MID(a,b) ((a+b)>>1)
#define fin(name) freopen(name,"r",stdin)
#define fout(name) freopen(name,"w",stdout)
#define clr(arr,val) memset(arr,val,sizeof(arr))
#define _for(i,start,end) for(int i=start;i<=end;i++)
#define FAST_IO ios::sync_with_stdio(false);cin.tie(0);
using namespace std;
typedef long long LL;
const int N=1e2+;
const int INF=0x3f3f3f3f;
const LL lim=(1LL<<); int mp[]={,,,,,,,,,,,,,,,};
LL top[N],dp[N][N]; //dp[pos][val]其中pos表示数位,val表示当前需要消耗的电路
char str[N]; LL dfs(bool limit,int pos,int val){
if(pos==-) return val;
if(!limit&&dp[pos][val]!=-) return dp[pos][val];
int up=limit?top[pos]:;
LL ans=;
for(int i=;i<=up;i++){
ans+=dfs(limit&&i==up,pos-,val+mp[i]);
}
if(!limit) dp[pos][val]=ans;
return ans;
} LL solve(LL x){
if(x==-) return ;
int cnt=-;
while(x){
top[++cnt]=x%;
x/=;
}
while(cnt<){
top[++cnt]=;
}
return dfs(,cnt,);
} int main(){
int t;
scanf("%d",&t);
memset(dp,-,sizeof(dp));
while(t--){
LL n,st;
scanf("%lld %llx",&n,&st);
LL ans;
if(st+n->=lim){
ans=solve((st+n-)%lim)+solve(lim-)-solve(st-);
}
else{
ans=solve(st+n-)-solve(st-);
}
printf("%lld\n",ans);
}
return ;
}