题解:学而思编程 奇特的数

【题目来源】

题目来源:奇特的数

【题目描述】

给定一个 \(n \times n\) 的矩阵 \(a\),其中第 \(i\) 行第 \(j\) 列的元素 \(a_{ij}\) 等于 \(i\times j(1 \le i,j \le n)\)

现在,给定一个整数 \(m\),请你计算 \(m\) 在矩阵中出现的次数。

【输入】

第一行一个整数 \(T\),表示共有 \(T\) 组测试数据。

每组数据包含两个整数 \(n,m\)

【输出】

每组数据输出一行一个结果,表示 \(m\) 在矩阵中出现的次数。

【输入样例】

2
3 6
3 3

【输出样例】

2
2

【核心思想】

  1. 问题分析:给定 \(n \times n\) 矩阵,其中 \(a_{ij} = i \times j\)\(1 \leq i, j \leq n\))。求整数 \(m\) 在矩阵中出现的次数。这是一个因子分解 + 约束计数问题,关键在于将矩阵元素转化为因子对,并统计满足条件的因子对数量。

  2. 算法选择

    • 因子对枚举\(a_{ij} = m\) 等价于 \(i \times j = m\),即 \((i, j)\)\(m\) 的一对因子
    • 边界约束筛选:因子对需满足 \(1 \leq i \leq n\)\(1 \leq j \leq n\)
  3. 关键步骤

    • 初始化:读取 \(T\)(测试组数)
    • 处理每组数据
      • 读取 \(n\)\(m\)
      • s = 0:计数器
      • 遍历 \(i\)\(1\)\(n\)
        • \(m \bmod i = 0\)\(i\)\(m\) 的因子):
          • \(j = m / i\)
          • \(j \leq n\)\(j\) 在矩阵列范围内):
            • s++:因子对 \((i, j)\) 满足条件
      • 输出 s
  4. 时间/空间复杂度

    • 时间复杂度:\(O(T \times n)\),每组数据遍历 \(1\)\(n\)
    • 空间复杂度:\(O(1)\),仅需常数变量
  5. 因子分解的核心思想

    • 矩阵元素结构\(a_{ij} = i \times j\) 将二维矩阵元素完全由行列下标的乘积决定,\(m\) 出现的次数等于 \(m\) 的因子对中两个因子均不超过 \(n\) 的对数
    • 单向枚举:固定 \(i\)\(1\)\(n\),则 \(j = m / i\) 唯一确定,只需验证 \(j\) 是否为整数且在范围内,避免 \(O(n^2)\) 的矩阵遍历
    • 对称性利用:因子对 \((i, j)\)\((j, i)\) 对应矩阵中不同位置(除非 \(i = j\)),枚举 \(i\) 时自然覆盖所有情况
    • 提前终止条件\(m \bmod i = 0\) 时才有必要计算 \(j\),减少无效运算
    • 适用于"乘积矩阵 + 值查询"类问题,因子分解将二维搜索降为一维枚举

【算法标签】

数学

【代码详解】

#include <bits/stdc++.h>
using namespace std;

int main()
{
    int T;  // 测试用例数
    cin >> T;
    for (int p = 0; p < T; p++)  // 处理每个测试用例
    {
        long long n, m;
        cin >> n >> m;  // 输入n和m

        long long s = 0;  // 计数器
        for (int i = 1; i <= n; i++)  // 遍历i从1到n
        {
            if (m % i == 0 && m / i <= n)  // 条件判断
            {
                s++;  // 满足条件,计数加1
            }
        }
        cout << s << endl;  // 输出结果
    }
    return 0;
}

【运行结果】

2
3 6
2
3 3
2
posted @ 2026-07-04 15:01  团爸讲算法  阅读(3)  评论(0)    收藏  举报