1. 算法竞赛中的经典问题解析
最近在准备算法竞赛的过程中,我遇到了几道非常有意思的题目。这些题目涵盖了数学计算、动态规划、贪心算法等多个领域,对于提升算法思维和编程能力很有帮助。下面我将详细解析这些题目的解题思路和实现方法。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 题目详解与解法分析
2.1 T1:整数分式求和问题
这道题目要求计算从1到n的所有整数除n的向下取整结果之和。直接暴力计算的时间复杂度是O(n),对于大数n来说效率太低。
2.1.1 优化思路
观察发现,当i超过√n后,n/i的结果会重复出现。我们可以利用这个性质将时间复杂度降低到O(√n)。具体做法是:
- 对于i从1到√n,直接计算n/i
- 对于大于√n的部分,找出使得n/i等于某个值的i的范围,然后批量计算
2.1.2 代码实现
cpp复制#include<iostream>
using namespace std;
int n;
long long ans = 0;
int main(){
cin >> n;
for (int i = 1; i <= n; i++){
int v = n / i;
int j = n / v;
ans += v * (j - i + 1);
i = j;
}
cout << ans;
return 0;
}
注意:这里的关键是找到使得n/i值相同的i的范围,然后一次性计算这个范围内的贡献。
2.2 T2:序列差的平方和
给定一个序列,要求计算所有无序数对差的平方之和。直接计算的时间复杂度是O(n²),对于大n不可行。
2.2.1 数学推导
我们可以将差的平方展开:
(a_i - a_j)² = a_i² - 2a_i a_j + a_j²
然后利用前缀和优化计算:
- 维护a_i的前缀和s
- 维护a_i²的前缀和s2
- 对于每个a_i,其贡献为(i-1)a_i² - 2a_i*s[i-1] + s2[i-1]
2.2.2 代码实现
cpp复制#include<iostream>
using namespace std;
int n, ans = 0;
int
