- 先考虑一些特殊情况比如 n > s n > s n>s与 n = s n=s n=s时
- 当 n > s n > s n>s时,可以想象这样是无解的
- 当 n = s n = s n=s时, b = n + 1 b = n + 1 b=n+1
- 然后呢,先考虑朴素做法:枚举 n n n以内所有数,作为 b b b。
- 当然 1 ≤ n ≤ 1 0 11 1\leq n \leq 10^{11} 1≤n≤1011,朴素做法肯定会TLE。
- 当然看这个范围,如果以 O ( n ) O(\sqrt n) O(n)的算法肯定可过。
- 我们就想想以 n \sqrt n n为分界线
- 小于 n \sqrt n n就可以直接枚举 b b b的值
- 而大于 n \sqrt n n时又会怎么样呢
- 可设整数 a , t a, t a,t使得 a ∗ b + t = n a * b + t = n a∗b+t=n与 a + t = s a+t=s a+t=s
- 那么我们有 ( b − 1 ) ∗ a = n − s (b-1)*a=n-s (b−1)∗a=n−s
- 那么答案就在 n − s n-s n−s的质因数中了。
- 枚举质因数,这道题就变成 O ( n ) O(\sqrt n) O(n)了。
code:
#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll n, s, ans = -1;
inline ll read() {
ll s = 0, f = 1;
char ch;
for(; ch < '0' || ch > '9'; ch = getchar()) if(ch == '-') f = -1;
for(; ch >= '0' && ch <= '9'; ch = getchar()) s = (s << 1) + (s << 3) + ch - '0';
return s * f;
}
inline ll f(ll b, ll n) {
ll ans = 0;
while(n) ans += n % b, n /= b;
return ans;
}
int main() {
n = read(), s = read();
ll u = sqrt(n) + 1;
for(ll i = 2; i <= u; ++i) if(f(i, n) == s) { ans = i; break; }
if(n == s) { ans = n + 1; }
if(ans == -1 && n > s) {
ll c = n - s;
u = c / (u - 1) + 1;
for(ll i = u; i >= 1; --i) {
ll b = c / i + 1;
if(!(c % i) && s >= i && (s - i) < b && i < b) {
ans = b;
break;
}
}
}
printf("%lld\n", ans);
return 0;
}
又是一道结论题