因为阶乘增长非常快,可能的 取值非常有限。对于每个
(跳过
),计算
,则原式化为
。
-
若
(即
): 取
(或其他
的正整数),差值为
。
-
若
: 要使绝对值最小,应让
尽可能接近
。最优
只可能为
或
,排除
后选取合法的候选值。
枚举每个合法候选 ,计算差值,更新最小值。
当 时,最小的差值为
(取
),且随着
增大,
单调递增,差值只会变大。因此当满足
且
当前已知最小差值时,即可终止枚举。若某次差值为
,可提前结束。
代码实现
#include <bits/stdc++.h>
#include <limits>
using namespace std;
using ll = long long;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
ll n;
cin >> n;
int ansX, ansY;
ll fac = 1LL;
ll minDiff = numeric_limits<ll>::max();
for (ll x = 1; x <= 13; x++) {
fac *= x;
if (x == 2)
continue;
ll K = fac - 1;
if (K == 0) {
minDiff = n;
ansX = 1;
ansY = 1;
continue;
}
ll q = n / K;
for (ll y = q; y <= q + 1; y++) {
if (y <= 0 || y == 2)
continue;
if (abs(y * K - n) < minDiff) {
minDiff = abs(y * K - n);
ansX = x;
ansY = y;
}
}
}
cout << ansX << " " << ansY << endl;
}
复杂度分析
-
时间复杂度: 枚举的
个数极少,因为
很快超过
。对于
,
最多到
;对于
,
最多到
左右。枚举次数是
级别,可视为常数
。每次迭代计算
和检查候选
均为
。
-
空间复杂度:
,仅需存储几个变量。

京公网安备 11010502036488号