Description
定义函数f(n,k),如果n在
Input
第一行输入一整数T表示用例组数,每组用例输入四个整数
(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~
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;
}