1 条题解
-
0
一、题意抽象
-
给定长度为 的正整数序列 ,且题目对每个公差 构造一个等差数列
-
定义
其中 是指示函数,“1” 表示条件成立,“0” 表示不成立。也就是说, 就是数有多少个下标 使得 能整除 。
-
要求最终答案
朴素做法:对每个 枚举所有 ,判断 。最坏是 ,当 达到 时不可行。
二、数学化简
二、观察与数学化简
判断条件
$$a_i \mid (i\cdot d) \;\Longleftrightarrow\; i\cdot d \equiv 0 \pmod{a_i} \;\Longleftrightarrow\; d \equiv 0 \pmod{\frac{a_i}{\gcd(a_i,i)}}. $$令
$$g_i = \gcd(a_i,\,i), \quad A_i' = \frac{a_i}{g_i}. $$则上式等价于
也就是说,对于固定的 ,只有当 是 的倍数时, 才为 1。
因此
我们要求
$$\sum_{d=1}^n S_d =\sum_{d=1}^n \sum_{i=1}^n \bigl[\,A_i'\mid d\,\bigr] =\sum_{i=1}^n \sum_{d=1}^n \bigl[\,A_i'\mid d\,\bigr]. $$对于固定的 ,在 中满足 的一共有 $\displaystyle \left\lfloor \tfrac{n}{A_i'}\right\rfloor$ 个。
于是
$$\sum_{d=1}^n S_d =\sum_{i=1}^n \Bigl\lfloor \frac{n}{A_i'}\Bigr\rfloor =\sum_{i=1}^n \Bigl\lfloor \frac{n}{\,a_i/g_i\,}\Bigr\rfloor. $$
三、从思路到代码
-
读取输入:,数组 。
-
遍历每个下标 :
- 计算 ;
- 令 ;
- 累加答案 += 。
-
输出累加结果。
此算法中每步 和一次除法、一次整除计数,都是 级别,整体 ,可轻松处理 。
四、代码
#include <bits/stdc++.h> using namespace std; using ll = long long; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); ll n; cin >> n; ll ans = 0; // 最终答案累加器 // 逐个读取 a_i,并即时累加对答案的贡献 for (ll i = 1; i <= n; i++) { ll ai; cin >> ai; // 1. 计算 g = gcd(i, ai) ll g = std::gcd(i, ai); // 2. 化简后得到 A' = ai / g // 只有当 d 是 A' 的倍数时,(i, d) 配对才算 valid ll Ap = ai / g; // 3. 在 d = 1..n 范围内,A' 的倍数共有 floor(n/Ap) 个 ans += n / Ap; } // 输出最终累加值 cout << ans << "\n"; return 0; } -
- 1
信息
- ID
- 176
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 2
- 标签
- 递交数
- 15
- 已通过
- 5
- 上传者