题目链接:点击打开链接
题解思路:因为以10进制来说,1位的回文串有9个,2位的有9个,3位的有90个,那么我们发现没差两位他们的倍增方式是乘以进制原始值为进制减一。那么我们就可以根据这个来事先打表。
代码:
#include <iostream>
#include <cstdio>
#include<set>
#include<algorithm>
using namespace std;
typedef long long ll;
const int mx = 2e5+10;
int a[37][mx],b[37];
ll find_ans(int index,int po)
{
ll res,cnt=0,w=0,num=po-1,half=1;
while(1)
{
if(w>0&&w%2==0) num*=po;
w++;
if(cnt+num>=index)
break;
cnt+=num;
}
index=index-cnt-1;//
int i;
for(i=0;i<(w-1)/2;i++) half*=po;
half+=index;
res=half;
if(w%2==1) half/=po;
while(half){
res=res*po+half%po;
half/=po;
}
return res;
}
int main(){
int t,cas = 1;
scanf("%d",&t);
for(int i=2;i<=36;i++){
int po = 1;
b[i] = 0;
ll ret = find_ans(po,i);
while(ret<=1e9){
a[i][b[i]++] = ret;
po++;
ret = find_ans(po,i);
}
}
while(t--){
int L,R,l,r;
ll ans = 0;
scanf("%d%d%d%d",&L,&R,&l,&r);
for(int i=l;i<=r;i++){
int lx = lower_bound(a[i],a[i]+b[i],L)-a[i];
int rx = upper_bound(a[i],a[i]+b[i],R)-a[i];
//cout << lx << " " <<rx << endl;
ans += 1ll*(rx-lx)*i;
ans += R-L-(rx-lx)+1;
}
printf("Case #%d: %lld\n",cas++,ans);
}
return 0;
}