1. 算法竞赛实战解析:从分块到BFS的六道经典题解
最近参加了一场算法竞赛,遇到了六道颇具代表性的题目,涵盖了分块算法、前缀和、动态规划、贪心、BFS等多种算法。作为算法竞赛爱好者,我想把这些题目的解题思路和实现细节分享给大家,特别是其中一些容易踩坑的地方。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. T1:分块算法解决数学求和问题
2.1 题目重述与分析
给定整数n,要求计算Σ⌊n/i⌋(i从1到n)。直接暴力计算的时间复杂度是O(n),当n很大时(比如1e12)会非常低效。
观察发现,⌊n/i⌋的值会形成多个连续的区间。例如n=100时:
- i∈[1,1]时,⌊100/i⌋=100
- i∈[2,2]时,⌊100/i⌋=50
- ...
- i∈[51,100]时,⌊100/i⌋=1
2.2 分块算法实现
分块算法的核心思想是找到每个相同⌊n/i⌋值的区间[i,j],然后一次性计算这个区间的贡献。
cpp复制#include<bits/stdc++.h>
using namespace std;
#define int long long
int n,sum;
signed main(){
cin>>n;
for(int i=1;i<=n;i++){
int val=n/i; // 当前区间的值
int r=n/val; // 区间的右端点
sum+=val*(r-i+1); // 区间[i,r]的贡献
i=r; // 跳过已处理的区间
}
cout<<sum;
}
注意事项:
- 必须使用long long类型,因为n和sum都可能很大
- i=r的赋值很关键,直接跳过已处理的区间
- 时间复杂度从O(n)优化到O(√n)
3. T2:前缀和优化差的平方和
3.1 问题转化
给定序列a,要求计算所有无序对(i,j)的(a_i-a_j)²之和。直接计算是O(n²)的,需要优化。
展开平方公式:
Σ(a_i-a_j)² = Σ(a_i² - 2a_ia_j + a_j²) = nΣa_i² - 2ΣΣa_ia_j
3.2 前缀和优化实现
利用前缀和可以在
