Seven Segment Display
Time Limit:2 Seconds Memory Limit: 65536 KB
A seven segment display, or seven segment indicator, is a form of electronic display device for displaying decimal numerals that is an alternative to the more complex dot matrix displays. Seven segment displays are widely used in digital clocks, electronic meters, basic calculators, and other electronic devices that display numerical information.
Edward, a student in Marjar University, is studying the course "Logic and Computer Design Fundamentals" this semester. He bought an eight-digit seven segment display component to make a hexadecimal counter for his course project.
In order to display a hexadecimal number, the seven segment display component needs to consume some electrical energy. The total energy cost for display a hexadecimal number on the component is the sum of the energy cost for displaying each digit of the number. Edward found the following table on the Internet, which describes the energy cost for display each kind of digit.
|
|
|
For example, in order to display the hexadecimal number "5A8BEF67" on the component for one second, 5 + 6 + 7 + 5 + 5 + 4 + 6 + 3 = 41 units of energy will be consumed.
Edward's hexadecimal counter works as follows:
- The counter will only work for n seconds. After n seconds the counter will stop displaying.
- At the beginning of the 1st second, the counter will begin to display a previously configured eight-digit hexadecimal numberm.
- At the end of the i-th second (1 ≤ i < n), the number displayed will be increased by 1. If the number displayed will be larger than the hexadecimal number "FFFFFFFF" after increasing, the counter will set the number to 0 and continue displaying.
Given n and m, Edward is interested in the total units of energy consumed by the seven segment display component. Can you help him by working out this problem?
Input
There are multiple test cases. The first line of input contains an integerT (1 ≤ T ≤ 105), indicating the number of test cases. For each test case:
The first and only line contains an integer n (1 ≤ n ≤ 109) and a capitalized eight-digit hexadecimal numberm (00000000 ≤ m ≤ FFFFFFFF), their meanings are described above.
We kindly remind you that this problem contains large I/O file, so it's recommended to use a faster I/O method. For example, you can use scanf/printf instead of cin/cout in C++.
Output
For each test case output one line, indicating the total units of energy consumed by the eight-digit seven segment display component.
Sample Input
3
5 89ABCDEF
3 FFFFFFFF
7 00000000
Sample Output
208
124
327
Hint
For the first test case, the counter will display 5 hexadecimal numbers (89ABCDEF, 89ABCDF0, 89ABCDF1, 89ABCDF2, 89ABCDF3) in 5 seconds. The total units of energy cost is (7 + 6 + 6 + 5 + 4 + 5 + 5 + 4) + (7 + 6 + 6 + 5 + 4 + 5 + 4 + 6) + (7 + 6 + 6 + 5 + 4 + 5 + 4 + 2) + (7 + 6 + 6 + 5 + 4 + 5 + 4 + 5) + (7 + 6 + 6 + 5 + 4 + 5 + 4 + 5) = 208.
For the second test case, the counter will display 3 hexadecimal numbers (FFFFFFFF, 00000000, 00000001) in 3 seconds. The total units of energy cost is (4 + 4 + 4 + 4 + 4 + 4 + 4 + 4) + (6 + 6 + 6 + 6 + 6 + 6 + 6 + 6) + (6 + 6 + 6 + 6 + 6 + 6 + 6 + 2) = 124.
题意:
有一个16进制的表,显示一个8位的16进制数,现在告诉你这个表要走n秒钟,每走1秒,在这一秒的结束时显示器的数字就+1,每显示一个数字,表需要耗费一定的能量
耗费的能量就是数字里面各个数位的上的数的消耗和
并且当显示的数字是FFFFFFFF时,+1是00000000
解析:
数位dp,dp[pos][state];state表示在pos以前累计的能量消耗
这道题需要用两维而不是直接用一维dp[pos]的原因是:
因为你每一次显示+1,你就要把前面所有的数字重新显示一遍,即使他们没有改变
例如2 00000000 (00000000,00000001)
这里你用一维的话,就只会得到答案50,48+2,就是前面都不变,只改变最后一位的花费
但是题目不是这样的,你每变一个数,需要把整个串重新显示一遍,计算花费。
所以你递归到最后一层的东西的花费,还跟前面的数字有关,所以还需要开一维来计算贡献。、
所以这道题的求和是前效性的,后面的与前面的相关,而前面只与他更前面的相关。(这句话是我瞎讲的,不看也可以)
#include<cstdio>
#include<cstring>
typedef long long int ll;
int a[100];
ll dp[10][100];
char str[20];
char s[20];
int val[16]={6,2,5,5,4,5,6,3,7,6,6,5,4,5,5,4};
int tran(char a)
{
if(a>='0'&&a<='9')
return a-'0';
else
return a-'A'+10;
}
//0为个位,1为十位,。。。。
ll dfs(int pos,bool limit,int state,bool lead) //计算dp[pos][state]即pos-1位是state时满足条件的个数
{
ll ans=0;
if(pos==-1)
{
return state;
}
if(!limit/*&&!lead*/&&dp[pos][state]!=-1)
{
return dp[pos][state]; //在非特殊情况下,直接返回之前已经算好的答案
}
int up=limit?a[pos]:15;
for(int i=0;i<=up;i++)
{
ans+=dfs(pos-1,limit&&i==up,state+val[i],i==0&&lead);
}
if(!limit/*&&!lead*/) dp[pos][state]= ans; //dp只记录普通情况下的值(因为特殊情况都要重新算,不能直接返回)
return ans;
}
ll solve(char ss[])
{
ll ans=0;
int pos=0;
for(int i=7;i>=0;i--)
{
a[pos++]=tran(ss[i]);
}
ans=dfs(pos-1,true,0,true);
return ans; //0被多算了pos-1次
}
int main()
{
int t;
ll n;
memset(dp,-1,sizeof(dp));
ll biao=solve("FFFFFFFF");
while(scanf("%d",&t)!=EOF)
{
while(t--)
{
scanf("%lld%s",&n,str);
n--;
int jin=n;
ll rest=0;
for(int i=7;i>=0;i--)
{
int cc=tran(str[i]);
rest+=val[cc];
cc+=jin;
if(cc>15)
{
jin=cc/16;
cc=cc%16;
}
else
{
jin=0;
}
if(cc>=0&&cc<=9)
{
s[i]=cc+'0';
}
else
{
s[i]=cc-10+'A';
}
}
if(jin==0)
printf("%lld\n",solve(s)-solve(str)+rest);
else
printf("%lld\n",biao-solve(str)+rest+solve(s));
}
}
return 0;
}