Description
定义一个数
K
是好数当且仅当存在
Input
第一行一个整数
T
表示用例组数,每组用例输入两个十进制数
Output
对于每组用例,输出区间 [L,R] 中好数的数量,结果模 998244353
Sample Input
2
5 20
123456 123456789
Sample Output
3
114480
Solution
求出
[1,n]
好数即可,
d
进制下的好数,其最小值为
Code
#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;
typedef long long ll;
#define maxn 5005
#define mod 998244353
int L[maxn],fact[maxn];
void init(int n=5000)
{
int len=1;
while(L[len]<=n)
{
len++;
L[len]=log10(len)*(len-1);
}
fact[0]=1;
for(int i=1;i<=n;i++)fact[i]=(ll)i*fact[i-1]%mod;
}
int dec(int x,int y)
{
return x-y<0?x-y+mod:x-y;
}
int inc(int x,int y)
{
return x+y>=mod?x+y-mod:x+y;
}
int T,a[maxn],b[maxn],c[maxn],mark[maxn];
char s[maxn];
int Deal(int *a,int len,int m)//把a转化成m进制
{
int n=0;
for(int i=1;i<=len;i++)c[i]=a[i];
while(len)
{
if(n>m)return n;
int pre=0;
for(int i=len;i;i--)
{
int temp=pre*10+c[i];
pre=temp%m,c[i]=temp/m;
}
b[++n]=pre;
while(len&&c[len]==0)len--;
}
return n;
}
int Count(int *a,int len,int m)
{
int n=Deal(a,len,m);
if(n<m)return 0;
if(n>m)return dec(fact[m],fact[m-1]);
for(int i=0;i<n;i++)mark[i]=0;
int ans=(ll)(b[n]-1)*fact[n-1]%mod;
mark[b[n]]=1;
for(int i=n-1;i;i--)
{
for(int j=0;j<b[i];j++)
if(!mark[j])ans=inc(ans,fact[i-1]);
if(mark[b[i]])break;
mark[b[i]]=1;
if(i==1)ans=inc(ans,1);
}
return ans;
}
int Solve(int *a,int len)
{
if(len==0)return 0;
int pos=2;
while(L[pos]<len)pos++;
int ans=dec(fact[pos-3],1);
for(int i=pos-2;i<pos;i++)ans=inc(ans,Count(a,len,i));
return ans;
}
int main()
{
init();
scanf("%d",&T);
while(T--)
{
scanf("%s",s+1);
int len=strlen(s+1);
for(int i=1;i<=len;i++)a[i]=s[len+1-i]-'0';
a[1]--;
for(int i=1;i<=len;i++)
if(a[i]<0)
a[i+1]--,a[i]+=10;
while(len&&a[len]==0)len--;
int ans=Solve(a,len);
scanf("%s",s+1);
len=strlen(s+1);
for(int i=1;i<=len;i++)a[i]=s[len+1-i]-'0';
ans=dec(Solve(a,len),ans);
printf("%d\n",ans);
}
return 0;
}