1 条题解

  • 1
    @ 2025-5-11 22:05:56

    题意分析

    乔治国王需要设计一个皇家陵园,陵园由多个正方形的墓群区域组成,每个区域的边长是连续的正整数,且所有区域的墓群数量(即边长的平方)互不相同。给定总墓穴数n,我们需要找出所有满足条件的陵园设计方案。每个方案由若干个连续的正整数边长组成,这些边长的平方和等于n。输出时,方案按区域数量从大到小排列。

    解题思路

    11.​问题转化​:我们需要找到所有连续的整数序列s,s+1,s+2,,s+l1s,s+1,s+2,…,s+l−1,使得这些数的平方和等于n。即:

    i=ss+l1i2=n\sum_{i=s}^{s+l-1} i^2 = n

    22.数学公式​:连续整数的平方和可以用公式表示。对于从a到b的连续整数平方和:

    $$\sum_{i=a}^{b} i^2 = \frac{b(b+1)(2b+1)}{6} - \frac{(a-1)a(2a-1)}{6} $$

    但直接计算这个和可能会比较复杂,我们可以采用滑动窗口的方法来高效地寻找满足条件的序列。

    33. (1)初始化两个指针leftleftrightright,从11开始。

    (2)维护一个当前和sumsum,表示从leftleftright1right−1的平方和。

    (3)如果sum<nsum<n,则增加rightright,并将right2right^ 2加到sumsum中。

    (4)如果sum==nsum==n,则找到一个有效序列[left,right1][left,right−1],记录下来。

    (5)如果sum>nsum>n,则增加left,并将left2left^ 2从sum中减去。

    (6)重复上述步骤直到leftleft超过可能的范围。

    44.边界条件

    (1)由于n可以达到101410^{ 14}rightright的最大可能值约为n\sqrt{n}​,即最多10710^ 7左右.

    (2)需要确保rightright不超过这个上限,避免无限循环。

    55.输出排序:找到所有方案后,按区域数量ll从大到小排序输出。

    代码

    #include <iostream>
    #include <vector>
    #include <algorithm>
    using namespace std;
    
    typedef long long ll;
    
    class GraveyardDesign {
    private:
    	ll num;
    	vector<vector<ll>> solutions;
    	
    	void saveSolution(ll left, ll right) {
    		vector<ll> solution;
    		solution.push_back(right - left + 1); // 区域数量
    		for (ll i = left; i <= right; ++i) {
    			solution.push_back(i); // 区域边长
    		}
    		solutions.push_back(solution);
    	}
    	
    public:
    	void setNum(ll n) {
    		num = n;
    		solutions.clear();
    	}
    	
    	void findSolutions() {
    		ll left = 1, right = 1;
    		ll sum = 0;
    		
    		while (true) {
    			// 扩展右边界直到sum >= num
    			while (sum < num && right <= 1e7) {  // 1e7是足够大的上限
    				sum += right * right;
    				++right;
    			}
    			
    			if (sum < num) break; // 无法再找到更大的和
    			
    			if (sum == num) {
    				saveSolution(left, right - 1);
    			}
    			
    			// 移动左边界
    			sum -= left * left;
    			++left;
    		}
    	}
    	
    	void printSolutions() {
    		// 按区域数量从大到小排序
    		sort(solutions.begin(), solutions.end(), 
    			[](const vector<ll>& a, const vector<ll>& b) {
    				return a[0] > b[0];
    			});
    		
    		cout << solutions.size() << "\n";
    		for (const auto& sol : solutions) {
    			for (size_t i = 0; i < sol.size(); ++i) {
    				cout << sol[i];
    				if (i != sol.size() - 1) cout << " ";
    			}
    			cout << "\n";
    		}
    	}
    };
    
    int main() {
    	GraveyardDesign solver;
    	ll num;
    	
    	while (cin >> num) {
    		solver.setNum(num);
    		solver.findSolutions();
    		solver.printSolutions();
    	}
    	
    	return 0;
    }
    
    • 1

    信息

    ID
    1101
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    7
    已通过
    1
    上传者