HDU

来源:互联网 发布:淘宝优惠券采集机器人 编辑:程序博客网 时间:2024/06/17 06:39

用数位DP求k进制的回文串个数,当时没想到数位DP过程中怎么记录回文的状态,还以为要把回文状态都记在dp数组里面。后来补了一下,发现只要开一个数组来存回文状态,因为dfs深搜过程中,过程之间互不影响,并且回文状态可以在那个数组上重复写入读出。

/*************************************************************************    > Author: MentalOmega    > Mail: 965194745@qq.com    > Created Time: 2017年8月20日    > function:数位dp ************************************************************************/#include<bits/stdc++.h>using namespace std;long long int dp[40][40][40];int dig[40];int getdig(int x,int base){    int pos=0;    while(x)    {        pos++;        dig[pos]=x%base;        x/=base;    }    return pos;}int num[40];//用于记录回文串中的字(关键long long int dfs(int pos,int len,int limit,int base)//pos表示的是处理到第pos位(从高到低),len表示的是回文串长度,limit表示的是这一位有没有限制,base是进制{    if(pos < 1)        return len!=0;//不能全是0    if(!limit && dp[pos][len][base] != -1)        return dp[pos][len][base];    int end = limit ? dig[pos] : base-1;    long long int ret = 0;    for(int i = 0; i <= end; i ++)    {        if(pos<=len/2&&i==num[pos])//这种情况是搜索到了回文串的后半部分            ret+=dfs(pos-1,len,limit && (i == end),base);        else if(len==0&&i)//选这一位做回文串的首位,那么长度就为pos那么长了        {            num[1]=i;            ret+=dfs(pos-1,pos,limit && (i == end),base);        }        else if(len&&pos>(len)/2)//这种情况是回文串的前半部分        {            num[len-pos+1]=i;            ret+=dfs(pos-1,len,limit && (i == end),base);        }        else if(len==0&&i==0)//这种是前导零来的        {            ret+=dfs(pos-1,0,limit && (i == end),base);        }    }    if(!limit)//没有限制的dp值可以记下        dp[pos][len][base]= ret;    return    ret;}long long solve(int r,int base){    int pos=getdig(r,base);    return dfs(pos,0,1,base);}int main(){    if (fopen("in.txt", "r") != NULL)    {        freopen("in.txt", "r", stdin);        // freopen("out.txt", "w", stdout);    }    memset(dp,-1,sizeof dp);    memset(num,-1,sizeof num);    int t;    cin>>t;    int icase=0;    while(t--)    {        printf("Case #%d: ",++icase);        int l,r,L,R;        scanf("%d%d%d%d",&l,&r,&L,&R);        long long ans=0;        for(int i=L;i<=R;i++)        {            long long ret = solve(r,i)-solve(l-1,i);            ans+=ret*i+r-l+1-ret;        }        printf("%lld\n",ans);    }    return 0;}