题目
题目描述
对于一个 n 维整数向量 v∈Zn,其在第 index 个维度上的取值记作 vindex。这里我们约定 index 的取值从 1 开始,即 v=(v1,v2,…,vn)。下面介绍一种向量的稀疏表示方法。
如果 v 仅在少量维度上的取值不为0,则称其为稀疏向量。
例如当 n=10 时,v=(0,0,0,5,0,0,-3,0,0,1) 就是一个稀疏向量。
由于稀疏向量的非零值较少,我们可以通过仅存储非零值的方式来节省空间。具体来说,每个非零值都可以用一个 (index, value)对来表示,即该向量在第 index 个维度上的取值 vindex=value≠0。在上面的例子中,v 就可以表示为[(4,5),(7,-3),(10,1)]。
接下来给出这种稀疏表示一般化的定义。
* 对于任意一个 n 维整数向量 v∈Zn,如果其在且仅在 a 个维度上取值不为0,则可以唯一表示为:
* 其中所有的 index 均为整数且满足:
* valuei表示向量 v 在对应维度 indexi 上的非零值。
给出两个 n 维整数向量 u,v∈Zn的稀疏表示,试计算它们的内积。
输入格式
从标准输入读入数据。
输入的第一行包含用空格分割的三个正整数 n、a 和 b,其中 n 表示向量 u、v 的维数,a 和 b 分别表示两个向量所含非零值的个数。
第二行到第 a+1 行输入向量 u 的稀疏表示。第 i+1 行(1 ≤ i ≤ a)包含用空格分割的两个整数 indexi 和 valuei,表示uindexi = valuei ≠ 0。
第 a+2 行到第 a+b+1 行输入向量 v 的稀疏表示。第 j+a+1 行(1 ≤ j ≤ b)包含用空格分割的两个整数 indexj 和 valuej,表示vindexj = valuej ≠ 0。
输出格式
输出到标准输出。
输出一个整数,表示向量 u 和 v 的内积 u·v。
样例
输入:
10 3 4
4 5
7 -3
10 1
1 10
4 20
5 30
7 40
输出:
-20
解释:
u = (0,0,0,5,0,0,-3,0,0,1)
v = (10,0,0,20,30,0,40,0,0,0)
u·v = 5x20 + (-3)x40 = -20
子任务
- 输入数据保证 0 < a,b < n;
- 向量 u 和 v 在每一维度上的取值的绝对值 |ui|,|vi|≤106(1≤i≤n)
分析
逻辑很简单,主要解决数据量大的问题。
代码
连续两次提交都是满分,都是泪。。。
import java.util.Scanner;
/**
* csp试题:稀疏向量 202006-2
* @author dxt
*
*/
public class Main {
public static void main(String[] args){
//1. 接收数据 n, a, b
int n, a, b;
Scanner scan = new Scanner(System.in);
n = scan.nextInt();
a = scan.nextInt();
b = scan.nextInt();
//2.1 接收向量 u 的稀疏表示数据
int[] u_index = new int[a];
int[] u_value = new int[a];
for(int i=0; i<a; i++){
u_index[i] = scan.nextInt();
u_value[i] = scan.nextInt();
}
//3. 初始化最后结果
long result = 0L;
int v_index, v_value;
int index_u = 0;
for(int i=0; i<b; i++){
v_index = scan.nextInt();
v_value = scan.nextInt();
while(index_u < a && i<a && index_u < b){
if(u_index[index_u] == v_index){
result += v_value * u_value[index_u];
index_u++;
break;
}else if(u_index[index_u] < v_index){
index_u++;
}else{
break;
}
}
}
//4. 输出结果
System.out.println(result);
}
}
总结
首先,while判断中加入了i<a
后,分数加了10分;然后将保存向量u的数据结构由一个a行2列的矩阵,改成了两个数组,分数加了20分;最后又在while判断中加了index_u < b
,期望能在减点运行时间。
这个问题其实使用map结构会很合适,但我用HashMap写的存在 运行超时 问题。