您的位置:首页 > 其它

HDU 6156 Palindrome Function(数位DP)

2018-01-22 18:22 459 查看
Description

定义函数f(n,k),如果n在k进制下是回文数则f(n,k)=k,否则f(n,k)=1,给出L,R,l,r,求∑i=LR∑j=lrf(i,j)

Input

第一行输入一整数T表示用例组数,每组用例输入四个整数L,R,l,r

(1≤T≤105,1≤L≤R≤109,2≤l≤r≤36)

Output

对于每组用例,输出答案

Sample Input

3

1 1 2 36

1 982180 10 10

496690841 524639270 5 20

Sample Output

Case #1: 665

Case #2: 1000000

Case #3: 447525746

Solution

进制范围较小,直接枚举,问题变成求1~N中有多少数字在d进制下为回文数,数位DP,以dp[len][pos][pre][sta]表示当前数字长度为len,当前在第pos位,上一位数字是pre,回文状态是sta(sta=1表示回文,sta=0表示不回文)的数字个数,如果在放前半部分直接放即可,放后半部分时候判断与对称位置数字是否相同来改变回文状态

Code

#include<cstdio>
#include<cstring>
using namespace std;
typedef long long ll;
int T,Case=1,L,R,l,r,a[37],b[37];
ll dp[37][37][37][2];
ll dfs(int len,int pos,int d,int sta,int fp)
{
if(!pos)
{
if(sta)return d;
return 1;
}
if(!fp&&~dp[len][pos][d][sta])return dp[len][pos][d][sta];
ll ans=0;
int fpmax=fp?a[pos]:d-1;
for(int i=0;i<=fpmax;i++)
{
b[pos]=i;
if(len==pos&&i==0)ans+=dfs(len-1,pos-1,d,sta,fp&&i==fpmax);
else if(sta&&pos<=len/2)ans+=dfs(len,pos-1,d,sta&&i==b[len+1-pos],fp&&i==fpmax);
else ans+=dfs(len,pos-1,d,sta,fp&&i==fpmax);
}
if(!fp)dp[len][pos][d][sta]=ans;
return ans;
}
ll Solve(int n,int d)
{
int len=0;
while(n)a[++len]=n%d,n/=d;
return dfs(len,len,d,1,1);
}
int main()
{
memset(dp,-1,sizeof(dp));
scanf("%d",&T);
while(T--)
{
scanf("%d%d%d%d",&L,&R,&l,&r);
ll ans=0;
for(int i=l;i<=r;i++)ans+=Solve(R,i)-Solve(L-1,i);
printf("Case #%d: %I64d\n",Case++,ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: