题解:学而思编程 整除子数组
【题目来源】
学而思编程:整除子数组
【题目描述】
给定一个长度为 \(n\) 的整数数组 \(a_1,a_2,\dots,a_n\),保证 \(0\le a_i\le 9\)。其中子数组 \(a_l\sim a_r\) 组成的整数为 \(num=a_l\times 10^{r-l}+a_{l+1}\times 10^{r-l-1}+\cdots + a_r\),请你计算能够被 \(4\) 整除的 \(a\) 数组的子数组的数量,子数组可以包含前导 \(0\)。
例如,如果数组 \(a=\{1,2,4\}\),则满足条件的子数组有 \(4\) 个:\(\{1,2\}\),\(\{4\}\),\(\{2,4\}\),\(\{1,2,4\}\);如果数组 \(a=\{0,4\}\),则满足条件的子数组有 \(3\) 个:\(\{0\}\),\(\{4\}\),\(\{0,4\}\)。
提示:若一个整数的末尾两位数能被 \(4\) 整除,则这个数能被 \(4\) 整除,例如 \(124\) 的末两位 \(24\%4==0\),所以 \(124\) 能被 \(4\) 整除。
【输入】
第一行一个整数 \(n\);
第二行 \(n\) 个整数 \(a_1,a_2,\dots,a_n\)。
【输出】
一行一个整数,表示满足条件的子数组数量。
【输入样例】
3
1 2 4
【输出样例】
4
【核心思想】
-
问题分析:给定长度为 \(n\) 的数组 \(a_1, a_2, \ldots, a_n\)(\(0 \leq a_i \leq 9\)),求有多少个子数组构成的整数能被 \(4\) 整除。利用数学性质:一个数能被 \(4\) 整除当且仅当它的末两位能被 \(4\) 整除。这是一个数学性质 + 分类计数问题。
-
算法选择:
- 单元素判断:长度为 \(1\) 的子数组,直接判断 \(a_i \bmod 4 = 0\)
- 末两位判断:长度 \(\geq 2\) 的子数组,只需判断由末两位 \(a_{i-1}a_i\) 组成的两位数是否能被 \(4\) 整除
-
关键步骤:
- 初始化:读取 \(n\) 和数组 \(a[1..n]\)
ans = 0- 遍历每个位置(\(i\) 从 \(1\) 到 \(n\)):
- 单元素子数组:
- 若 \(a_i \bmod 4 = 0\):
ans++(单个 \(a_i\) 能被 \(4\) 整除)
- 若 \(a_i \bmod 4 = 0\):
- 长度 \(\geq 2\) 的子数组(\(i > 1\)):
- 若 \((a_{i-1} \times 10 + a_i) \bmod 4 = 0\):
ans += (i - 1):以 \(a_{i-1}a_i\) 为末两位的所有子数组都满足条件,前缀有 \(i-1\) 个选择(起始位置可以是 \(1\) 到 \(i-1\))
- 若 \((a_{i-1} \times 10 + a_i) \bmod 4 = 0\):
- 单元素子数组:
- 输出
ans
-
时间/空间复杂度:
- 时间复杂度:\(O(n)\),线性遍历
- 空间复杂度:\(O(n)\),存储数组
-
数学性质的核心思想:
- 4 的整除判定:一个整数能被 \(4\) 整除当且仅当它的末两位组成的数能被 \(4\) 整除。因此长度 \(\geq 2\) 的子数组只需关注末两位
- 前缀扩展性:若末两位 \(a_{i-1}a_i\) 能被 \(4\) 整除,则所有以这两位结尾的子数组(起始位置从 \(1\) 到 \(i-1\))都满足条件,共 \(i-1\) 个
- 单元素特殊处理:长度为 \(1\) 时无"末两位",需单独判断 \(a_i \bmod 4\)
- 前导零无关:子数组可包含前导零,不影响数值计算和整除判定
- 适用于"末位整除性质 + 子数组计数"类问题,数学性质将复杂枚举简化为线性扫描
【算法标签】
数学
【代码详解】
#include <bits/stdc++.h>
using namespace std;
int a[1000010]; // 存储数字数组
int main()
{
int n;
cin >> n; // 输入数字个数
long long ans = 0; // 使用long long防止溢出
for (int i = 1; i <= n; i++) // 遍历每个数字
{
cin >> a[i]; // 输入当前数字
// 单个数字能被4整除
if (a[i] % 4 == 0)
{
ans++;
}
// 与前一个数字组成的两位数能被4整除
if (i > 1 && (a[i - 1] * 10 + a[i]) % 4 == 0)
{
ans += (i - 1); // 加上前缀子数组个数
}
}
cout << ans << endl; // 输出结果
return 0;
}
【运行结果】
3
1 2 4
4
浙公网安备 33010602011771号