十四届浙江省赛 E题(数位DP)

来源:互联网 发布:苏州有mac专柜吗 编辑:程序博客网 时间:2024/05/16 16:17

题意不说了,已经讨论过了。

如果知道数位DP的话,那么这个题就是数位DP的裸题,而且还属于比较简单那种......

dp[i][j],表示i位,前i 位的权值和为 j

这个题有一点要注意的就是前导0也有算花费。

我在DFS中,只有在搜索到最后一位时,才维护了前导的权值和。

因为要保证整个DFS 的有效性,返回的是第pos位,权值和为sum的总花费。


#include<stdio.h>#include<algorithm>#include<string>#include<string.h>#include<queue>#include<vector>#include<stack>#include<math.h>#include<map>#include<set>#include<iostream>using namespace std;#define INF 0x7f7f7f7f#define LL long longconst LL mod=1e9+7;LL mask=4294967295;LL dp[20][60],v[20]={6,2,5,5,4,5,6,3,7,6,6,5,4,5,5,4};int a[20];LL q(int x){    LL tmp=1;    for(int i=1;i<=x;i++)        tmp*=16;    return tmp;}LL dfs(int pos,int sum,int limit){    if(pos==-1)        return 0;    if(!limit&&dp[pos][sum]!=-1)        return dp[pos][sum];    int up=limit ? a[pos]:15;    LL ret=0;    for(int i=0;i<=up;i++)    {        ret+=dfs(pos-1,sum+v[i],limit&&i==a[pos]); //后面的        if(pos==0)        {            ret+=v[i]*q(pos);                           //这一位            ret+=sum*q(pos);        }    }    if(!limit)        dp[pos][sum]=ret;    return ret;}LL solve(LL x){    if(x<0)        return 0;    if(x==0)        return 48;    int pos=0;    while(x)    {        a[pos++]=x%16;        x/=16;    }    return dfs(pos-1,v[0]*(8-pos),true);}int main(){    int t;    scanf("%d",&t);    memset(dp,-1,sizeof(dp));    while(t--)    {        LL n,x;        scanf("%lld %llX",&n,&x);        n--;        if(x+n>mask)        {            LL ans=solve(mask)-solve(x-1);            ans+=solve(0+(n+x-mask-1));            printf("%lld\n",ans);        }        else            printf("%lld\n",solve(n+x)-solve(x-1));    }return 0;}

0 0