成对乘积之和
集合 X = {a, b, c} 的成对乘积可以定义为所有可能的集合对的乘积之和。集合的对为 Y = {a * a, a * b, a *c, b * b, b * c, c * c},其中乘积是可交换的。因此,集合 X 的成对乘积是集合 Y 元素的总和,即 aa + ab + ac + bb + bc + cc。
在数学术语中,所有可能的对乘积之和可以表示为:
$$\mathrm{\displaystyle\sum\limits_{i=1,j=i}^{i\leq n,j\leq n}\:(i,j)=i\times j}$$
问题陈述
给定一个数字 n。找到范围 (1, n) 内所有成对乘积之和,包括 n 和 1。
示例 1
Input: n = 4
Output: 65
说明
i 的范围是从 1 到 4,j 的范围是从 i 到 4。
1*1 + 1*2 + 1*3 + 1*4 + 2*2 + 2*3 + 2*4 + 3*3 + 3*4 + 4*4 = 1 + 2 + 3 + 4 + 4 + 6 + 8 + 9 + 12 + 16 = 65
示例 2
Input: n = 10
Output: 1705
说明
i 的范围是从 1 到 10,j 的范围是从 i 到 10。
1*1 + 1*2 + … + 1*10 + 2*2 + 2*3 + … + 2*10 + 3*3 + 3*4 + … + 3*10 + 4*4 + 4*5 + … 4*10 + 5*5 + 5*6 + … + 5*10 + 6*6 + 6*7 + … 6*10 + 7*7 + 7*8 + … 7*10 + 8*8 + 8*9 + 8*10 + 9*9 + 9*10 + 10*10 = 1705
方法 1:暴力方法
该问题的暴力解决方案是使用两个 for 循环迭代范围内的所有可能的对,其中第一个循环迭代 1 到 n,第二个循环迭代第一个数字到 n。
伪代码
procedure pairwiseProduct (n) sum = 0 for i = 1 to n for j = i to n sum = sum + (i * j) end procedure
示例:C++ 实现
在以下程序中,我们找到所有可能的对,然后找到乘积之和。
#include <bits/stdc++.h> using namespace std; // Function to find pairwise product over the range 1 to n, 1 and n inclusive unsigned long long pairwiseProduct(unsigned int n){ unsigned long long sum = 0; // First number: 1 <= i <= n for (unsigned int i = 1; i <= n; i++){ // Second number: i <= j <= n for (unsigned int j = i; j <= n; j++){ sum += i * j; } } return sum; } int main(){ unsigned long long n = 9; cout << "Pairwise Product = " << pairwiseProduct(n); return 0; }
输出
Pairwise Product = 1155
时间复杂度 - O(n^2)
空间复杂度 - O(1)
方法 2
以 n = 4 为例:
Sum = 1*1 + 1*2 + 1*3 + 1*4 + 2*2 + 2*3 + 2*4 + 3*3 + 3*4 + 4*4
简化以上公式:
Sum = 1*1 + (1+2)*2 + (1+2+3)*3 + (1+2+3+4)*4
取 prefix_sum[1] = 1,
prefix_sum[2] = 1+2,
prefix_sum[3] = 1+2+3,
prefix_sum[2] = 1+2,
伪代码
procedure pairwiseProduct (n) sum = 0 prefixSum = 0 for i = 1 to n prefixSum = prefixSum + 1 sum = sum + i * prefixSum end procedure
示例:C++ 实现
在以下程序中,我们在每次迭代中找到总和(即前缀和),乘以迭代次数,并在每一步中添加到最终总和。
#include <bits/stdc++.h> using namespace std; // Function to find pairwise product over the range 1 to n, 1 and n inclusive unsigned long long pairwiseProduct(unsigned int n){ unsigned long long sum = 0; unsigned long long prefixSum = 0; for (unsigned int i = 1; i <= n; i++){ prefixSum += i; sum += i * prefixSum; } return sum; } int main(){ unsigned long long n = 9; cout << "Pairwise Product = " << pairwiseProduct(n); return 0; }
输出
Pairwise Product = 1155
结论
总之,为了找到范围 1 到 n 内数字的成对乘积之和(包括 1 和 n),我们可以遵循上述两种方法中的任何一种,其中第一种是暴力方法,时间复杂度为 O(n^2),第二种方法是使用前缀和计算成对乘积之和的优化方法,时间复杂度为 O(n)。