题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5594
【题意】显示器显示16进制数,并给出显示各个数字耗电;给出需要显示的时间和初始显示的数,给出总耗电量
【分析】
如果普通模拟的话是会超时的,这里要用到数位dp;
n秒后如果没超过FFFFFFFF 就直接solve(r)-solve(l-1);
如果超过的话要做减法再做加法:
r%=(fill_hex+1);//注意取余的时候是要+1的
printf("%lld\n",solve(fill_hex)-solve(l-1)+solve(r));
数位dp模板:
typedef long long ll;
int a[20];
ll dp[20][state];
ll dfs(int pos,bool lead,bool limit)
{
if(pos==-1) return 1;
if(!limit && !lead && dp[pos][state]!=-1) return dp[pos][state];
int up=limit?a[pos]:9;
ll ans=0;
for(int i=0;i<=up;i++)
{
if() ...
else if()...
ans+=dfs(pos-1,lead && i==0,limit && i==a[pos]) //最后两个变量传参都是这样写的
}
if(!limit && !lead) dp[pos][state]=ans;
return ans;
}
ll solve(ll x)
{
int pos=0;
while(x)
{
a[pos++]=x%10;
x/=10;
}
return dfs(pos-1,true,true);
}
int main()
{
ll le,ri;
while(~scanf("%lld%lld",&le,&ri))
{
printf("%lld\n",solve(ri)-solve(le-1));
}
}
【本题代码】
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll fill_hex=4294967295;//FFFFFFFF
int num[16]={6,2,5,5,4,5,6,3,7,6,6,5,4,5,5,4};
int a[20];
ll dp[20][100];
ll l,r,n;
ll dfs(int pos,ll sum,bool limit)
{
if(pos==-1)return sum;
if(!limit && dp[pos][sum]!=-1) return dp[pos][sum];
int up=limit?a[pos]:15;
ll ans=0;
for(int i=0;i<=up;++i)
ans+=dfs(pos-1,sum+num[i],limit&&i==a[pos]);
if(!limit)dp[pos][sum]=ans;
return ans;
}
ll solve(ll x)
{
for(int i=0;i<8;++i)
{
a[i]=x%16;
x/=16;
}
return dfs(7,0,true);
}
int main()
{
int t;scanf("%d",&t);
while(t--)
{
memset(dp,-1,sizeof(dp));
scanf("%lld %llX",&r,&n);
r=r-1+n;
l=n;
if(r>fill_hex)
{
r%=(fill_hex+1);//注意取余的时候是要+1的
printf("%lld\n",solve(fill_hex)-solve(l-1)+solve(r));
}
else printf("%lld\n",solve(r)-solve(l-1));
}
return 0;
}