我的生日快到了!唉,但如今我已经老了,我想重新获得年轻的感觉。
幸运的是,我想出了一个让人感觉更年轻的好方法:如果我把我的年龄以适当选择的 b b b进制书写,那么它看起来会更小。例如,假设我以 10 10 10进制书写的年龄是 32 32 32岁;以 16 16 16进制书写,它只有 20 20 20( 0 x 20 0x20 0x20)!
然而,在这样做时,我不能选择任意进制数。如果以 b b b进制为数写的我的年龄包含 0 − 9 0-9 0−9以外的数字,那么很明显我在作弊,这违背了目的。此外,如果我的年龄的进制数 b b b太小,那么很明显我在作弊。
在我希望我的年龄看起来有多小的问题上,考虑到我的年龄 y y y和下限 l l l,找到最大的进制数 b b b,这样写在基数 b b b中的 y y y只包含十进制数字,并且当将其看做一个十进制数字时至少是 l l l。
输入由一行组成,其中包含两个 10 10 10进制的整数 y y y ( 10 ≤ y ≤ 1 0 18 10\le y\le10^{18} 10≤y≤1018 –是的,我很老)和 l l l( 10 ≤ l ≤ y 10\le l \le y 10≤l≤y)
如上所述,输出最大进制数 b b b。
时间限制: 1 s 1s 1s,内存限制: 1 G B 1GB 1GB
32 20
16
2016 100
42
我们考虑枚举y转成b进制时的那个数(记为 x x x)。
首先考虑到 x x x 不用枚举太多,因为当 x x x 太大时, b b b 会很小,那时只需要枚举 b b b 就行了。
经过本人的多次测试: x x x 只要枚举到 1000 1000 1000 ,剩下到靠枚举 b b b 即可。
接下来我们考虑枚举 x x x 怎么做:
①: x x x 是一个两位数,设它是 a 1 × 10 + b 1 a_1\times 10+b_1 a1×10+b1,则我们可以解一个一元一次方程: a 1 ⋅ b + a 2 = x a_1\cdot b+a_2=x a1⋅b+a2=x,可以轻松解出 b b b。
②: x x x 是一个三位数,设它是 a 1 × 1 0 2 + a 2 × 10 + a 3 a_1\times 10^2+a_2\times 10+a_3 a1×102+a2×10+a3,则我们可以解一个一元三次方程: a 1 ∗ b 2 + a 2 ∗ b + a 3 = x a_1*b^2+a_2*b+a_3=x a1∗b2+a2∗b+a3=x,即 a 1 ∗ b 2 + a 2 ∗ b + ( a 3 − x ) = 0 a_1*b^2+a_2*b+(a_3-x)=0 a1∗b2+a2∗b+(a3−x)=0,利用求根公式 b = − b ± b 2 − 4 ⋅ a ⋅ c 2 ⋅ a b=\frac{-b±\sqrt{b^2-4\cdot a\cdot c}}{2\cdot a} b=2⋅a−b±b2−4⋅a⋅c,可以快速求出根,但是注意要使用__int128
或 long double
。
这样枚举 x x x 就完成了。
接下来考虑枚举 b b b 怎么做:
将 b b b 从 1e6
开始往下枚举,每次都将 y y y 转换成 b b b 进制,然后判断是否有一位大于 9 9 9,最后再和 l l l 比较一下即可。
for(register int i=max(l,10ll);i<=99;++i){
int a=i/10,b=i%10;//找ap+b=y
if((y-b)%a==0){
ans=max(ans,(y-b)/a);
}
}
for(register int i=max(l,100ll);i<=999;++i){
Int a=i/100,b=i/10%10,c=i%10-y;//求a*p^2+b*p+c=0
Int nick=b*b-4*a*c;
if(nick<0)
continue;
nick=Sqrt(nick);
Int p1=-b+nick,p2=-b-nick;
p1=p1/(2*a),p2=p2/(2*a);
for(int pp=1;pp<=2;pp++)
{
Int L=p1-20,R=p1+20;
if(L<10)
L=10;
for(Int xp=L;xp<=R;++xp){
Int sum=a*xp*xp+b*xp+c;
if(sum==0){
if(xp>ans)
ans=xp;
break;
}
}
swap(p1,p2);
}
}
其中Int
表示__int128
for(register int i=1e6;i>=10;--i){
if(i<ans){
break;
}
zhuan(i);
if(!check())
continue;
if(cmp()){
ans=max(ans,i);
break;
}
}
inline void zhuan(int x){
cct=0;
int p=y;
while(p){
cc[++cct]=p%x;
p/=x;
}
for(register int i=1;i<=cct/2;++i)
swap(cc[i],cc[cct-i+1]);
return;
}
inline bool check(){
for(register int i=1;i<=cct;++i){
if(cc[i]>9)
return false;
}
return true;
}
inline bool cmp(){
int ans=0;
for(register int i=1;i<=cct;++i)
ans=ans*10+cc[i];
if(ans>=l)
return true;
else
return false;
}
Int Read(){
Int x=0,f=1;
char ch=getchar();
while(!isdigit(ch)&&ch!='-')ch=getchar();
if(ch=='-')f=-1,ch=getchar();
while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
return f*x;
}
void print(Int x){
if(x<0)putchar('-'),x=-x;
if(x>9)print(x/10);
putchar(x%10+'0');
}
Int Sqrt(Int x){
Int L=1,R=1000000000000000;
while(L<R){
Int mid=L+R;
mid=mid/2;
if(mid*mid<x){
L=mid+1;
}
else{
R=mid;
}
}
for(Int i=L-5;i<=L+5;++i){
if(i*i<=x&&(i+1)*(i+1)>x){
return i;
}
}
return -1;
}
#include
using namespace std;
#define int long long
#define Int __int128
#define doudle long double
inline int read();
int y,l;
int cc[1377];
int cct;
int ans;
inline void zhuan(int x){
cct=0;
int p=y;
while(p){
cc[++cct]=p%x;
p/=x;
}
for(register int i=1;i<=cct/2;++i)
swap(cc[i],cc[cct-i+1]);
return;
}
inline bool check(){
for(register int i=1;i<=cct;++i){
if(cc[i]>9)
return false;
}
return true;
}
inline bool cmp(){
int ans=0;
for(register int i=1;i<=cct;++i)
ans=ans*10+cc[i];
if(ans>=l)
return true;
else
return false;
}
Int Read(){
Int x=0,f=1;
char ch=getchar();
while(!isdigit(ch)&&ch!='-')ch=getchar();
if(ch=='-')f=-1,ch=getchar();
while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
return f*x;
}
void print(Int x){
if(x<0)putchar('-'),x=-x;
if(x>9)print(x/10);
putchar(x%10+'0');
}
Int Sqrt(Int x){
Int L=1,R=1000000000000000;
while(L<R){
Int mid=L+R;
mid=mid/2;
if(mid*mid<x){
L=mid+1;
}
else{
R=mid;
}
}
for(Int i=L-5;i<=L+5;++i){
if(i*i<=x&&(i+1)*(i+1)>x){
return i;
}
}
return -1;
}
signed main(){
y=read(),l=read();
for(register int i=max(l,10ll);i<=99;++i){
int a=i/10,b=i%10;//找ap+b=y
if((y-b)%a==0){
ans=max(ans,(y-b)/a);
}
}
for(register int i=max(l,100ll);i<=999;++i){
Int a=i/100,b=i/10%10,c=i%10-y;//求a*p^2+b*p+c=0
Int nick=b*b-4*a*c;
if(nick<0)
continue;
nick=Sqrt(nick);
Int p1=-b+nick,p2=-b-nick;
p1=p1/(2*a),p2=p2/(2*a);
for(int pp=1;pp<=2;pp++)
{
Int L=p1-20,R=p1+20;
if(L<10)
L=10;
for(Int xp=L;xp<=R;++xp){
Int sum=a*xp*xp+b*xp+c;
if(sum==0){
if(xp>ans)
ans=xp;
break;
}
}
swap(p1,p2);
}
}
for(register int i=1e6;i>=10;--i){
if(i<ans){
break;
}
zhuan(i);
if(!check())
continue;
if(cmp()){
ans=max(ans,i);
break;
}
}
printf("%llu\n",ans);
return 0;
}
inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}return x*f;}