题解链接
https://www.lucien.ink/archives/230/
题目链接
https://arc060.contest.atcoder.jp/tasks/arc060_b
题目
Problem Statement
For integers b(b≥2) and n(n≥1), let the function f(b,n) be defined as follows:
, when
, when
Here,
denotes the largest integer not exceeding
, and n mod
denotes the remainder of
divided by
.
Less formally, is equal to the sum of the digits of n written in base . For example, the following hold:
You are given integers
and
. Determine if there exists an integer
such that
. If the answer is positive, also find the smallest such
.
Constraints
,
are integers.
Input
The input is given from Standard Input in the following format:
n
s
Output
If there exists an integer such that , print the smallest such . If such does not exist, print instead.
题意
给你一个n
和一个s
,问是否存在一个
,使得n
在
进制下各位数字的和为s
,如果存在,则输出这个
,如果不存在,则输出-1
。
思路
假设
为n
在
进制下的各位数字(
为最低位),那么有:
考虑某个进制
,使得n
在
进制下的表示的最高次幂大于等于
次幂,则有:
,于是我们在
进制的最高次为2次幂及以上的时候直接暴力枚举即可。
对于最高次为一次幂的
,等式为:
将 式移项并代入 式得:
于是我们可以从大到小枚举 (相当于从小到大枚举 ),判断一下是否存在合法 的即可。
因为前面我们枚举 的时候已经枚举过 的范围,而 显然小于 ,所以我们第二次枚举只用枚举 这个区间就可以了。
实现
#include <bits/stdc++.h>
long long n, s;
bool check(long long base) {
long long ret = 0, tmp = n;
while (tmp) ret += tmp % base, tmp /= base;
return ret == s;
}
bool check(long long a1, long long tmp, long long a0 = 0, long long b = 0) {
return (a0 = s - a1) >= 0 && a0 < (b = tmp / a1 + 1) && a1 < b;
}
int main() {
scanf("%lld%lld", &n, &s);
long long up = (long long)sqrt(n) + 1;
for (long long base = 2; base <= up; base++) if (check(base)) return 0 * printf("%lld\n", base);
if (n <= s) return 0 * printf("%lld\n", n < s ? -1: n + 1);
long long tmp = n - s, upper = tmp / up + 1;
for (long long a1 = upper; a1 >= 1; a1--)
if (!(tmp % a1) && check(a1, tmp)) return 0 * printf("%lld\n", tmp / a1 + 1);
return 0 * puts("-1");
}