题解 进制转换
- 貌似 powl 的精度比 pow 要高
打表发现 \(\frac{n}{1},\cdots,\frac{n}{10}\) 这几个值附近出答案的概率较高
然后再乱开几次根号爆扫再爆扫较小的可以拿很多分
然后正解:
首先枚举 b 是 \(O(\text{炸天})\) 的
所以尝试枚举 a
发现先将 \(m\leqslant 8\) 枚举完之后,剩下的有 \(b\leqslant 100\)
考虑已知 a 求 b
首先有一个二分的做法,复杂度很假
一下并不知如何想到的题解做法:
发现 \(a_mb^m\) 很大,尝试用这个东西卡界
有
右面那个东西是 \(a_i\leqslant 9\) + 等比数列求和
题解说这个范围并不大所以可以爆扫
题解还说这样的复杂度大约是 \(O(300\lg)\) 的
点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 1000010
#define ll long long
#define int long long
char buf[1<<21], *p1=buf, *p2=buf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf, 1, 1<<21, stdin)), p1==p2?EOF:*p1++)
inline int read() {
int ans=0, f=1; char c=getchar();
while (!isdigit(c)) {if (c=='-') f=-f; c=getchar();}
while (isdigit(c)) {ans=(ans<<3)+(ans<<1)+(c^48); c=getchar();}
return ans*f;
}
char tem[N]; int top2;
inline void writeln(int t) {
do {tem[++top2]=t%10+'0'; t/=10;} while (t);
while (top2) printf("%c", tem[top2--]);
printf("\n");
}
int y, l;
int divd[N], dcnt;
int sta[N], top;
namespace force{
inline bool tran(int y, int b) {
top=0;
do {sta[++top]=y%b; if (y%b>9) return 0; y/=b;} while (y);
if (dcnt!=top) return top>dcnt;
for (int i=top; i; --i) if (sta[i]!=divd[i]) return sta[i]>divd[i];
return 1;
}
void solve() {
int tl=l; dcnt=0;
do {divd[++dcnt]=tl%10; tl/=10;} while (tl);
//for (int i=dcnt; i; --i) cout<<divd[i]<<' '; cout<<endl;
for (int i=y; i; --i) if (tran(y, i)) {printf("%lld\n", i); return ;}
}
}
namespace task1{
bool tran(int y, int b) {
top=0;
do {sta[++top]=y%b; if (y%b>9) return 0; y/=b;} while (y);
return 1;
}
bool check() {
if (dcnt!=top) return top>dcnt;
for (int i=top; i; --i) if (sta[i]!=divd[i]) return sta[i]>divd[i];
return 1;
}
void solve() {
int tl=l; dcnt=0;
do {divd[++dcnt]=tl%10; tl/=10;} while (tl);
for (int i=1; i<=9; ++i) {
for (int j=0; ; ++j) {
if (!tran(y, y/i-j)) break;
if (check()) {printf("%lld\n", y/i-j); return ;}
}
}
int lim=sqrt(y);
for (int i=lim; i; --i) if (tran(y, i)&&check()) {printf("%lld\n", i); return ;}
}
}
namespace task2{
int ans; bool down;
unordered_map<ll, bool> mp;
bool tran(int y, int b) {
top=0;
do {sta[++top]=y%b; if (y%b>9) return 0; y/=b;} while (y);
return 1;
}
bool check() {
if (dcnt!=top) return top>dcnt;
for (int i=top; i; --i) if (sta[i]!=divd[i]) return sta[i]>divd[i];
return 1;
}
void init() {
int tl=l; dcnt=ans=0; mp.clear(); down=0;
do {divd[++dcnt]=tl%10; tl/=10;} while (tl);
}
void calc(int lim) {
if (lim<=ans) return ;
if (mp.find(lim)!=mp.end()) return ;
mp[lim]=1;
if (lim<=20000) {
if (down) return ;
down=1;
for (int i=lim; i>ans; --i) if (tran(y, i)&&check()) {ans=max(ans, i); return ;}
return ;
}
for (int i=1; i<=9; ++i) {
for (int j=0; ; ++j) {
if (lim/i-j<=ans) break;
if (!tran(y, lim/i-j)) break;
if (check()) {ans=max(ans, lim/i-j); return ;}
}
}
calc(ceil(pow(lim, 1.0/2)));
calc(ceil(pow(lim, 1.0/3)));
calc(ceil(pow(lim, 1.0/5)));
calc(ceil(pow(lim, 1.0/7)));
}
void solve() {
init();
calc(y);
for (int i=200000; i>ans; --i) if (tran(y, i)&&check()) ans=max(ans, i);
printf("%lld\n", ans);
}
}
namespace task3{
int ans;
unordered_map<ll, bool> mp;
bool tran(int y, int b) {
top=0;
do {sta[++top]=y%b; if (y%b>9) return 0; y/=b;} while (y);
return 1;
}
bool check() {
if (dcnt!=top) return top>dcnt;
for (int i=top; i; --i) if (sta[i]!=divd[i]) return sta[i]>divd[i];
return 1;
}
void init() {
int tl=l; dcnt=ans=0; mp.clear();
do {divd[++dcnt]=tl%10; tl/=10;} while (tl);
}
void calc(int lim) {
if (lim<=ans) return ;
if (mp.find(lim)!=mp.end()) return ;
mp[lim]=1;
if (lim<=100) {
for (int i=lim; i>ans; --i) if (tran(y, i)&&check()) {ans=max(ans, i); return ;}
return ;
}
for (int i=1; i<=9; ++i) {
for (int j=0; ; ++j) {
if (lim/i-j<=ans) break;
if (!tran(y, lim/i-j)) break;
if (check()) {ans=max(ans, lim/i-j); return ;}
}
}
calc(ceil(pow(lim, 1.0/2)));
calc(ceil(pow(lim, 1.0/3)));
calc(ceil(pow(lim, 1.0/5)));
calc(ceil(pow(lim, 1.0/7)));
}
void solve() {
init();
calc(y);
for (int i=ans+1; i<=y; ++i) {
if (tran(y, i)&&check()) ans=i;
if ((i&1) && clock()>950000) break;
}
printf("%lld\n", ans);
}
}
namespace task{
inline int qpow(int a, int b) {ll ans=1; for (; b; a=a*a,b>>=1) if (b&1) ans*=a; return ans;}
inline bool tran(int y, int b) {
top=0;
do {sta[++top]=y%b; if (y%b>9) return 0; y/=b;} while (y);
if (dcnt!=top) return top>dcnt;
for (int i=top; i; --i) if (sta[i]!=divd[i]) return sta[i]>divd[i];
return 1;
}
void solve() {
int tl=l; dcnt=0;
do {divd[++dcnt]=tl%10; tl/=10;} while (tl);
for (int m=log10(l); m<=8; ++m) {
for (int am=1; am<=9; ++am) {
auto inlimit = [&](int b){ll t=qpow(b, m); return y<=am*t+9*((t-1)/(b-1));};
for (int b=ceil(powl(y/am, 1.0L/m)),t; b>100&&(t=qpow(b,m),y<=am*t+9*((t-1)/(b-1))); --b)
if (tran(y, b)) {writeln(b); return ;}
}
}
for (int i=100; i; --i) if (tran(y, i)) {writeln(i); return ;}
}
}
signed main()
{
freopen("number.in", "r", stdin);
freopen("number.out", "w", stdout);
int T=read();
// if (T==1) {
// y=read(); l=read();
// if (y<=10000) force::solve();
// else if (y<=1000000000) task1::solve();
// else task3::solve();
// }
// else {
// while (T--) {
// y=read(); l=read();
// task2::solve();
// }
// }
while (T--) {
y=read(); l=read();
task::solve();
}
return 0;
}