题解:学而思编程 整除子数组

【题目来源】

学而思编程:整除子数组

【题目描述】

给定一个长度为 \(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

【核心思想】

  1. 问题分析:给定长度为 \(n\) 的数组 \(a_1, a_2, \ldots, a_n\)\(0 \leq a_i \leq 9\)),求有多少个子数组构成的整数能被 \(4\) 整除。利用数学性质:一个数能被 \(4\) 整除当且仅当它的末两位能被 \(4\) 整除。这是一个数学性质 + 分类计数问题。

  2. 算法选择

    • 单元素判断:长度为 \(1\) 的子数组,直接判断 \(a_i \bmod 4 = 0\)
    • 末两位判断:长度 \(\geq 2\) 的子数组,只需判断由末两位 \(a_{i-1}a_i\) 组成的两位数是否能被 \(4\) 整除
  3. 关键步骤

    • 初始化:读取 \(n\) 和数组 \(a[1..n]\)
    • ans = 0
    • 遍历每个位置\(i\)\(1\)\(n\)):
      • 单元素子数组
        • \(a_i \bmod 4 = 0\)ans++(单个 \(a_i\) 能被 \(4\) 整除)
      • 长度 \(\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\)
    • 输出 ans
  4. 时间/空间复杂度

    • 时间复杂度:\(O(n)\),线性遍历
    • 空间复杂度:\(O(n)\),存储数组
  5. 数学性质的核心思想

    • 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
posted @ 2026-07-05 14:33  团爸讲算法  阅读(3)  评论(0)    收藏  举报