1 条题解

  • 0
    @ 2026-10-26 10:54:56

    思路与算法

    设总共有k家,自家门牌为a。所有门牌总和S=k(k+1)/2,其余门牌之和为S-a,题目再减去自家门牌的两倍,得到S-3a=n。因此枚举k,若S-n为正、能被3整除,且a=(S-n)/3不超过k,就得到合法候选。输入保证唯一解,找到后输出a和k。

    当S-n>3k时,即使a取最大的k也无法满足等式,应结束枚举。此时k已大于3,而S-3k=k(k-5)/2在后续严格递增,因此不会漏掉更后面的解。

    正确性说明

    枚举到的每个候选均满足1<=a<=k和S-3a=n,所以重新计算其他各家门牌之和减去2a恰为n,是合法答案。任意合法解(k,a)都有S-n=3a,必满足正数、整除和边界检查;只要尚有可能存在合法a,枚举都不会提前终止,所以合法解一定被找到。题目保证唯一,输出第一个合法候选即为唯一答案。

    复杂度

    由n>=k(k-5)/2及n<100000,候选k小于450;循环次数O(sqrt(n)+1),每次O(1),总时间O(sqrt(n)+1),额外空间O(1),初始化O(1)。总和及差值使用long long。独立数据核验枚举了全部k<=450与自家门牌,构建完整范围解表,仅选择恰有一个解的输入。

    易错点

    减去的是自家门牌的三倍:先从总和删去自家一次,再减两次。输出顺序是自家门牌、总户数。不能把任意n<100000都当成合法数据;例如99999有两个解,不符合唯一性保证。本批最大合法唯一n为99997。

    参考代码(C++11)

    #include <iostream>
    using namespace std;
    int main() {
        long long n;
        cin >> n;
        for (long long count = 1;; ++count) {
            long long total = count * (count + 1) / 2;
            if (total - n > 3 * count)
                break;
            long long difference = total - n;
            if (difference > 0 && difference % 3 == 0 && difference / 3 <= count) {
                cout << difference / 3 << ' ' << count << '\n';
                return 0;
            }
        }
    }
    
    • 1

    信息

    ID
    1705
    时间
    1000ms
    内存
    64MiB
    难度
    进阶
    标签
    递交数
    1
    已通过
    1
    上传者