[数位dp] HDU 6156 Palindrome Function
题目大意
定义函数 \(f(n,k)\),当 \(n\) 在 \(k\) 进制下为回文数时,\(f(n,k)=k\),不是回文数是 \(f(n,k)=1\)。给定 \(L,R,l,r(1\leq L\leq R\leq 10^9,2\leq l\leq r\leq 36)\),求\(\sum_{i=L}^R\sum_{j=l}^r f(i,j)\)。
题解
数位dp。设 \(dp[base][pos][len]\) 表示在 \(base\) 进制下,枚举到第 \(pos\) 位,不含前导零的数字的长度为 \(len\) 时的回文数个数。
Code
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#include <cstdio>
#include <vector>
#include <map>
using namespace std;
#define RG register int
#define LL long long
template<typename elemType>
inline void Read(elemType &T){
elemType X=0,w=0; char ch=0;
while(!isdigit(ch)) {w|=ch=='-';ch=getchar();}
while(isdigit(ch)) X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
T=(w?-X:X);
}
LL dp[37][33][50];
int a[100],Num[50];
int T,Base;
LL DFS(int pos,bool limit,bool lead,int Len){
if(!pos) return Len?1:0;
if(!limit && !lead && dp[Base][pos][Len]!=-1) return dp[Base][pos][Len];
int up=limit?a[pos]:(Base-1);
LL Res=0;
for(int i=0;i<=up;++i){
if(lead && i==0){
Res+=DFS(pos-1,limit && i==up,true,Len-1);
continue;
}
if((Len&1) && pos==((Len+1)>>1)) Res+=DFS(pos-1,limit && i==up,lead && i==0,Len);
else if(Len-pos>=Len/2){
if(i!=Num[Len-pos+1]) continue;
Res+=DFS(pos-1,limit && i==up,lead && i==0,Len);
}else{
Num[pos]=i;
Res+=DFS(pos-1,limit && i==up,lead && i==0,Len);
}
}
if(!limit && !lead) dp[Base][pos][Len]=Res;
return Res;
}
LL Solve(LL x,LL base){
int pos=0;
while(x){a[++pos]=x%base;x/=base;}
return DFS(pos,true,true,pos);
}
int main(){
memset(dp,-1,sizeof(dp));
LL L,R,l,r;
Read(T);int Case=0;
while(T--){
Read(L);Read(R);Read(l);Read(r);
LL Ans=0;
for(LL k=l;k<=r;++k){
Base=k;
LL temp=Solve(R,k)-Solve(L-1,k);
Ans+=temp*k+(R-L+1-temp);
}
printf("Case #%d: %lld\n",++Case,Ans);
}
return 0;
}