题意
数字时钟每秒钟会消耗显示的数字所需的能量,给定时间长度m和起点st,求m秒内会消耗的能量
思路
没有什么比看错题目却一直没发现更悲催的了。。。
队友和我说了题意,然后我想都没想就开始写了,一直以为前导零是不需要计算代价的,虽然样例就是有前导零的。。
就这样带着错误的思路打了三个小时。。
好吧,不怪队友,谁让自己连样例都不看呢。。
这题的打法很多,延续昨天想到的思路,用数位dp来做
我们用dp[i][j]表示长度为i,以j开头,形式为jxxxx所需的代价总和。
因为后面的x的范围一定是0000-FFFF,所以代价可以直接推算出来
如果是0000-FFFF,那么一共有16^4个数字,0-F各出现(16^3)*4次,其实和数位dp已经没太大关系了,毕竟是可以直接推出答案而不需要递推的
代码(前导零不计代价,错误思路)
思路错了以后代码实现更复杂一些,但是也是能用数位dp做出来的
#include <bits/stdc++.h>
#define mem(a,b) memset(a,b,sizeof(a))
#define rep(i,a,b) for(int i=a;i<b;i++)
#define sc(a) scanf("%d",&a)
const int INF=0x3f3f3f3f;
const int maxn=2e5+50;
const int mod=1e9+7;
const double eps=1e-8;
#define pii pair<int,int>
typedef long long ll;
typedef unsigned int ui;
using namespace std;
ll val[16]={6,2,5,5,4,5,6,3,7,6,6,5,4,5,5,4};
inline ll pow16(ll i){
return (1ll<<(i*4));
}
inline char toChar(int x){
assert(x>=0 && x<16);
if(x>=0 && x<=9) return x+'0';
return x+'A'-10;
}
inline int toInt(char x){
if(x>='0' && x<='9') return x-'0';
return x-'A'+10;
}
ll bruteForce(int x){
ll ret=0;
while(x>=0){
char buf[66]={0};
sprintf(buf,"%08X",x);
if(x==0) ret+=val[0];
int len=strlen(buf);
int pos=0;
while(buf[pos]=='0') pos++;
for(;pos<8;pos++) ret+=val[toInt(buf[pos])];
x--;
}
return ret;
}
string toHex(ll x){
string ret="";
for(int i=0;i<8;i++){
ret=toChar(x%16)+ret;
x=x/16;
}
return ret;
}
ll toLL(char buf[]){
ll ret=0;
int len=strlen(buf);
rep(i,0,len) ret=ret*16+toInt(buf[i]);
return ret;
}
//dp i j len-i start-j tot-val
ll dp[9][17];
//dp[i][0] no-leading-zeros
//dp[i][16] start with 0 and have leading-zeros
void init(){
mem(dp,0);
rep(i,0,16) dp[1][i]=val[i];
dp[1][16]=val[0];
rep(i,2,9){
rep(j,0,16) dp[i][0]+=dp[i-1][j];
ll num=pow16(i-1);
rep(j,1,16){
dp[i][j]=val[j]*num+num/16*(i-1)*78;
}
dp[i][16]=val[0]*num+num/16*(i-1)*78;
}
rep(i,1,5) rep(j,0,17) printf("%d %d %lld\n",i,j,dp[i][j]);
}
ll st,ed;
ll LIM=0xFFFFFFFF;
void debugHex(int x){
printf("%08X\n",x);
}
ll cal(ll x){
if(x<0) return 0;
if(x==0) return 6;
string buf=toHex(x);
bool flag=true;
int pos=0;
while(buf[pos]=='0') pos++;
int num;
ll base=0;
ll ret=0;
for(;pos<8;pos++){
int i=8-pos;
num=toInt(buf[pos]);
if(num){
if(flag){
ret+=dp[i][0];
}else ret+=dp[i][16]+base*pow16(i-1);
flag=false;
}
rep(j,1,num){
ret+=dp[i][j]+base*pow16(i-1);
}
if(pos==7) ret+=dp[i][num]+base*pow16(i-1);
base+=val[num];
printf("i:%d pos:%d num:%d base:%lld ret:%lld\n",i,pos,num,base,ret);
}
return ret;
}
int main()
{
#ifndef ONLINE_JUDGE
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
#endif
init();
char buf[233];
while(~scanf("%s",buf)){
st=toLL(buf);
cout<<"= ="<<cal(st)<<" normal "<<bruteForce(st)<<endl;
}
int T; sc(T);
while(T--){
int n;
scanf("%d %s",&n,buf);
st=toLL(buf);
ed=(st+n-1)%LIM;
debugHex(st);
debugHex(ed);
ll ans;
if(st<=ed){
ans=cal(ed)-cal(st-1);
}else{
ans=cal(LIM)-cal(st-1)+cal(ed-1);
}
printf("%lld\n",ans);
}
return 0;
}
代码(按照题意)
#include <bits/stdc++.h>
#define mem(a,b) memset(a,b,sizeof(a))
#define rep(i,a,b) for(int i=a;i<b;i++)
#define sc(a) scanf("%d",&a)
const int INF=0x3f3f3f3f;
const int maxn=2e5+50;
const int mod=1e9+7;
const double eps=1e-8;
#define pii pair<int,int>
typedef long long ll;
typedef unsigned int ui;
using namespace std;
ll val[16]={6,2,5,5,4,5,6,3,7,6,6,5,4,5,5,4};
inline ll pow16(ll i){
return (1ll<<(i*4));
}
inline char toChar(int x){
assert(x>=0 && x<16);
if(x>=0 && x<=9) return x+'0';
return x+'A'-10;
}
inline int toInt(char x){
if(x>='0' && x<='9') return x-'0';
return x-'A'+10;
}
ll bruteForce(int x){
ll ret=0;
while(x>=0){
char buf[66]={0};
sprintf(buf,"%08X",x);
rep(pos,0,8) ret+=val[toInt(buf[pos])];
x--;
}
return ret;
}
string toHex(ll x){
string ret="";
for(int i=0;i<8;i++){
ret=toChar(x%16)+ret;
x=x/16;
}
return ret;
}
ll toLL(char buf[]){
ll ret=0;
int len=strlen(buf);
rep(i,0,len) ret=ret*16+toInt(buf[i]);
return ret;
}
//dp i j len-i start-j tot-val
ll dp[9][16];
//dp[i][0] start with 0 and have leading-zeros
void init(){
mem(dp,0);
rep(i,0,16) dp[1][i]=val[i];
dp[1][16]=val[0];
rep(i,2,9){
ll num=pow16(i-1);
rep(j,0,16) dp[i][j]=val[j]*num+num/16*(i-1)*78;
}
//rep(i,1,5) rep(j,0,16) printf("%d %d %lld\n",i,j,dp[i][j]);
}
ll st,ed;
ll LIM=0xFFFFFFFF;
void debugHex(int x){
printf("%08X\n",x);
}
ll cal(ll x){
if(x<0) return 0;
if(x==0) return 6;
string buf=toHex(x);
int pos=0,num;
ll base=0,ret=0;
while(buf[pos]=='0') {
pos++;
base+=val[0];
}
for(;pos<8;pos++){
int i=8-pos;
num=toInt(buf[pos]);
ll sz=pow16(i-1);
rep(j,0,num){
ret+=dp[i][j]+base*sz;
}
if(pos==7) ret+=dp[i][num]+base*sz;
base+=val[num];
//printf("i:%d pos:%d num:%d base:%lld ret:%lld\n",i,pos,num,base,ret);
}
return ret;
}
int main()
{
#ifndef ONLINE_JUDGE
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
#endif
init();
char buf[233];
// while(~scanf("%s",buf)){
// st=toLL(buf);
// cout<<"= ="<<cal(st)<<" normal "<<bruteForce(st)<<endl;
// }
int T; sc(T);
while(T--){
int n;
scanf("%d %s",&n,buf);
st=toLL(buf);
ed=(st+n-1)%LIM;
// debugHex(st);
// debugHex(ed);
ll ans;
if(st<=ed){
ans=cal(ed)-cal(st-1);
}else{
ans=cal(LIM)-cal(st-1)+cal(ed-1);
}
printf("%lld\n",ans);
}
return 0;
}