原题解链接:https://ac.nowcoder.com/discuss/150263
解法很多,比如DP,贪心,二分。
题解里提供二分的解法。
时间复杂度
我们发现,最后交出来的答案的区间在小进制下一定连续的。
所以我们考虑,所以我们二分出答案区间在小进制下的左右端点,然后做差就是答案。
注意,特判两段区间没交集的时候请输出0而不是负数或者其他的结果。
#include<bits/stdc++.h>
using namespace std;
long long change_m_10(const char *s,int m)//把m进制的s转换成10进制数并返回
{
if(s[0]=='+')
{
return change_m_10(s+1,m);
}
if(s[0]=='-')
{
return change_m_10(s+1,m)*-1;
}
long long sum=0;
int l=strlen(s);
for(int i=0;i<l;i++)
{
if(s[i]>='A'&&s[i]<='Z')
{
sum=sum*m+s[i]-'A'+10;
}
else
{
sum=sum*m+s[i]-'0';
}
}
return sum;
}
void change_10_m(long long x,int m,char s[])//把10进制的x转换成m进制并存入s数组
{
const char f[20]="0123456789ABCDEF";
int stk[105],top=0;
bool sign;
sign=x<0;
if(sign)x*=-1;
if(!x)
{
s[0]='0';
s[1]='\0';
return;
}
while(x)
{
int a=x%m;
x=x/m;
if(a<0)
{
x++;
a=a-m;
}
stk[++top]=a;
}
int l=0;
if(sign)
{
s[l++]='-';
}
while(top)
{
s[l++]=f[stk[top--]];
}
s[l]='\0';
return;
}
long long change(const char *s)
{
long long ans=0;
int l=strlen(s);
for(int i=0;i<l;i++)
{
ans=ans*10+s[i]-'0';
}
return ans;
}
int T,J1,J2;
string l1,r1,l2,r2;
char save[105];
long long L,R;
int main()
{
scanf("%d",&T);
while(T--)
{
scanf("%d %d",&J1,&J2);
cin>>l1>>r1>>l2>>r2;
if(J1>J2)
{
swap(J1,J2);
swap(l1,l2);
swap(r1,r2);
}
string temp;
temp.clear();
for(int i=1;i<=18;++i)
{
temp+='0'+J1-1;
}
L=0;
R=change_m_10(temp.c_str(),J1);
long long x=change(l2.c_str());
long long ansx;
while(L<=R)
{
long long mid=(L+R)/2;
change_10_m(mid,J1,save);
if(change(save)>=x)
{
ansx=mid;
R=mid-1;
}
else
{
L=mid+1;
}
}
L=0;
R=change_m_10(temp.c_str(),J1);
long long y=change(r2.c_str());
long long ansy;
while(L<=R)
{
long long mid=(L+R)/2;
change_10_m(mid,J1,save);
if(change(save)<=y)
{
ansy=mid;
L=mid+1;
}
else
{
R=mid-1;
}
}
long long ansl=change_m_10(l1.c_str(),J1);
long long ansr=change_m_10(r1.c_str(),J1);
ansl=max(ansl,ansx);
ansr=min(ansr,ansy);
printf("%lld\n",max(ansr-ansl+1,0LL));
}
return 0;
}