HDU 6156 数位DP

来源:互联网 发布:快刀软件 编辑:程序博客网 时间:2024/05/16 23:44

题意

给一个区间,求这个区间内的所有数在A进制到B进制下(回文数的个数*进制)+非回文数的个数。

题解

其实就是很普通的数位DP,只不过在状态记录上比较新颖。状态记录不再使用函数参数记录状态,而是使用一个数组来记录每一位的状态,因为DP是递归调用的,所以可以在对后面需要和前面相同的位进行判断,只有相同的情况才能进行下一步DFS。

代码

#include <iostream>#include<cstdio>#include<algorithm>#include<cstring>#include<vector>#include<cmath>#include<queue>#include<string>#include<set>#include<map>#include<bitset>#include<stack>#include<string>#define UP(i,l,h) for(int i=l;i<h;i++)#define DOWN(i,h,l) for(int i=h-1;i>=l;i--)#define W(a) while(a)#define MEM(a,b) memset(a,b,sizeof(a))#define LL long long#define INF 0x3f3f3f3f#define MAXN 800010#define MOD 1000000009#define EPS 1e-10#define int LLusing namespace std;int dp[50][50][50];int dig[50],tmp[50];int dfs(int len,int pos,int base,bool up){    if(len==0)        return 1;    if(!up&&dp[len][pos][base]!=-1){        return dp[len][pos][base];    }    int n=up?dig[len]:base-1;    int ans=0;    UP(i,0,n+1){        tmp[len]=i;        if(len==pos&&!i){            ans+=dfs(len-1,pos-1,base,i==n&&up);        }        else if(len>pos/2){            ans+=dfs(len-1,pos,base,i==n&&up);        }else if(tmp[pos-len+1]==i){            ans+=dfs(len-1,pos,base,i==n&&up);        }    }    if(!up){        dp[len][pos][base]=ans;    }    return ans;}int solve(int x,int base){    MEM(dig,0);    int len=0;    W(x){        dig[++len]=x%base;        x/=base;    }    return dfs(len,len,base,true);}main(){    int t;    scanf("%I64d",&t);    int ks=1;    MEM(dp,-1);    W(t--){        int a,b,x,y;        scanf("%I64d%I64d%I64d%I64d",&a,&b,&x,&y);        int ans=0;        UP(i,x,y+1){            int tp=solve(b,i)-solve(a-1,i);            ans+=(tp*i+(b-a+1-tp));        }        printf("Case #%I64d: %I64d\n",ks++,ans);    }}