因为阶乘增长非常快,可能的 取值非常有限。对于每个 (跳过 ),计算 ,则原式化为

  • (即 ): 取 (或其他 的正整数),差值为

  • : 要使绝对值最小,应让 尽可能接近 。最优 只可能为 ,排除 后选取合法的候选值。

枚举每个合法候选 ,计算差值,更新最小值。

时,最小的差值为 (取 ),且随着 增大, 单调递增,差值只会变大。因此当满足 当前已知最小差值时,即可终止枚举。若某次差值为 ,可提前结束。

代码实现

#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;
}

复杂度分析

  • 时间复杂度: 枚举的 个数极少,因为 很快超过 。对于 最多到 ;对于 最多到 左右。枚举次数是 级别,可视为常数 。每次迭代计算 和检查候选 均为

  • 空间复杂度,仅需存储几个变量。