「14行AC」一道被低估的数论好题:O(n log n) 解整除对计数#算法 #C++ #数论 #编程竞赛 #力扣

# 算法题解:等差数列整除对总数(C++ 高效实现)

> **语言**:C++17  
> **发布时间**:2026年1月1日  
> **时间复杂度**:O(n log M),M = max(aᵢ)  
> **空间复杂度**:O(1)  
> **关键词**:数论、gcd、贡献法、整除优化

---

## 🚀 C++ 代码实现(AC 友好)

```cpp
#include <iostream>
#include <vector>
#include <algorithm>
#include <cctype>
using namespace std;

// 手写 gcd(C++17 可用 __gcd 或 std::gcd,但为兼容性自实现)
long long gcd(long long a, long long b) {
    return b == 0 ? a : gcd(b, a % b);
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int n;
    cin >> n;
    vector<long long> a(n);
    for (int i = 0; i < n; ++i) {
        cin >> a[i];
    }

    long long ans = 0;
    // 遍历每个位置 i(从1开始编号)
    for (int i = 1; i <= n; ++i) {
        long long ai = a[i - 1];
        long long g = gcd(ai, static_cast<long long>(i));
        // 贡献值:floor(n * g / ai)
        ans += (n * g) / ai;
    }

    cout << ans << '\n';
    return 0;
}

✅ 正确性验证(对应样例)

输入:

4
2 2 3 1

计算过程:

i aᵢ gcd(aᵢ, i) 贡献 = ⌊4 × g / aᵢ⌋
1 2 gcd(2,1)=1 4×1/2 = 2
2 2 gcd(2,2)=2 4×2/2 = 4
3 3 gcd(3,3)=3 4×3/3 = 4
4 1 gcd(1,4)=1 4×1/1 = 4
总和 14

输出:

14

⚙️ 编译与运行建议

  • 编译命令(推荐)

    g++ -std=c++17 -O2 -pipe -static -s solution.cpp -o solution
    
  • 输入输出重定向测试

    ./solution < input.txt > output.txt
    
  • 支持数据范围:n ≤ 2×10⁵,aᵢ ≤ 10⁹(使用 long long 防溢出)

💡 n * g 最大约为 2e5 × 1e9 = 2e14long long(最大约 9e18)可安全容纳。


🔍 算法核心思想回顾

  1. 转换求和顺序
    \sum_{d=1}^n \sum_{i=1}^n [a_i \mid i \cdot d]
    改为 \sum_{i=1}^n \#\{ d \in [1,n] \mid a_i \mid i \cdot d \}

  2. 数论推导
    a_i \mid i \cdot d \iff d \equiv 0 \pmod{\frac{a_i}{\gcd(a_i,i)}}
    → 满足条件的 d 个数为 \left\lfloor \dfrac{n \cdot \gcd(a_i, i)}{a_i} \right\rfloor

  3. 规避除零与溢出

    • 输入保证正整数,无需判 0
    • 使用 long long 防止中间结果溢出


> ✅ 代码已在本地用 GCC 11.4 + C++17 测试通过  
> 📦 无 STL 以外依赖,适合 OJ / 面试手写  
> 🌟 亮点:**手写 gcd 增强可移植性**、**I/O 加速提升性能**、**防溢出设计严谨**
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容