题解 进制转换

传送门

  • 貌似 powl 的精度比 pow 要高

打表发现 \(\frac{n}{1},\cdots,\frac{n}{10}\) 这几个值附近出答案的概率较高
然后再乱开几次根号爆扫再爆扫较小的可以拿很多分

然后正解:
image
首先枚举 b 是 \(O(\text{炸天})\)
所以尝试枚举 a
发现先将 \(m\leqslant 8\) 枚举完之后,剩下的有 \(b\leqslant 100\)
考虑已知 a 求 b
首先有一个二分的做法,复杂度很假
一下并不知如何想到的题解做法:
发现 \(a_mb^m\) 很大,尝试用这个东西卡界

image
右面那个东西是 \(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;
}
posted @ 2022-02-19 16:05  Administrator-09  阅读(1)  评论(0编辑  收藏  举报