题目链接
题目描述
给定三个正整数 ,根据一系列规则构造并计算矩阵
。最终任务是计算矩阵
所有元素的和,并四舍五入到最近的整数。
是
的全1矩阵。
是
的“上三角全1”矩阵。
解题思路
直接模拟矩阵运算是不可行的。本题的核心是利用矩阵的特殊结构进行数学推导和简化。
-
分析
是一个所有元素为1的
矩阵。它的每一行都是一个长度为
的全1向量。
是相同的
矩阵,我们称之为
。
当且仅当
。
的计算方式相同,所以
。我们以
为例。
的第
行是由
的第
行(全1向量)乘以
得到的。
的第
行第
列的元素
等于
的第
行与
的第
列的点积。由于
的行是全1的,这等价于
的第
列的元素之和。
的第
列 (
-indexed) 中,值为1的元素是
,其中
。因此,第
列的和是
。
- 所以,
的每一行都是同一个向量
。
-
分析
和
。由于
且
的每一行都是
,
的每一列都是
。
的任意元素
都是
。这是一个常数。
- 因此,
是一个
的矩阵,其所有元素都相等。
函数按行操作。对于一个所有元素都相等的行向量
(长度为
),
之后的结果是
。
- 所以,
是一个所有元素都为
的
矩阵。
-
分析
。
的任意元素
等于
的第
行与
的第
列的点积。
的第
行是
。
的第
列的所有
个元素都等于
的第
个分量,即
。
- 所以
。
- 这说明
的每一行都等于向量
。
-
计算总和
- 问题最终简化为计算矩阵
的所有元素之和。
是一个
矩阵,每一行都是
。
- 总和 =
。
- 我们分两种情况计算这个和:
- Case 1:
:
。和为
。总和为
。
- Case 2:
: 和可以拆分为两部分:
。总和为
。
- Case 1:
- 问题最终简化为计算矩阵
代码
#include <iostream>
#include <numeric>
#include <cmath>
using namespace std;
using ll = long long;
int main() {
ll n, m, h;
cin >> n >> m >> h;
double sum_one_row = 0;
if (h <= m) {
sum_one_row = (double)h * (h + 1) / 2.0;
} else {
sum_one_row = (double)m * (m + 1) / 2.0 + (double)(h - m) * m;
}
double total_sum = n * sum_one_row;
cout << round(total_sum) << endl;
return 0;
}
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
long n = sc.nextLong();
long m = sc.nextLong();
long h = sc.nextLong();
double sumOneRow = 0;
if (h <= m) {
sumOneRow = (double)h * (h + 1) / 2.0;
} else {
sumOneRow = (double)m * (m + 1) / 2.0 + (double)(h - m) * m;
}
double totalSum = n * sumOneRow;
System.out.println(Math.round(totalSum));
}
}
import sys
import math
n, m, h = map(int, sys.stdin.readline().split())
sum_one_row = 0
if h <= m:
sum_one_row = h * (h + 1) / 2
else:
sum_one_row = m * (m + 1) / 2 + (h - m) * m
total_sum = n * sum_one_row
print(round(total_sum))
算法及复杂度
- 算法:数学推导与简化
- 时间复杂度:
,因为我们只进行了几次基本的算术运算。
- 空间复杂度:
,只需要常数空间存储输入的
和中间结果。