1. 程式人生 > 其它 >「csp模式試題 202006-2」稀疏向量 C/C++

「csp模式試題 202006-2」稀疏向量 C/C++

技術標籤:筆記cspc++演算法c語言

目錄

  • 題目
  • 輸入輸出樣例
  • 題解思路
  • 題解原始碼(c/c++)

題目 :稀疏向量

【問題描述】

對於一個 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,則可以唯一表示為:

[(index1,value1),(index2,value2),...,(indexa,valuea)]

其中所有的 index 均為整數且滿足:

1≤index1<index2<...<indexa小於等於n

valuei 表示向量 V 在對應維度上 indexi 上的非零值。

給出兩個 n 維整數向量 U,V∈Zⁿ 的稀疏表示,試計算他們的內積。

U·V=∑ui*vi (i:1->n)

【輸入格式】

從標準輸入讀入資料。

輸入的第一行包含用空格分割的三個正整數 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。

輸入輸出樣例

  • 輸入樣例1
10 3 4
4 5
7 -3
10 1
1 10
4 20
5 30
7 40
  • 輸出樣例1
-20

樣例 1 解釋

U=(0,0,0,5,0,0,-3,0,0,1)

V=(10,0,0,20,30,0,40,0,0)

U·V=5*20 +(-3)*40=-20

【子任務】

輸入資料保證 0<a,b<n;

向量 U 和 V 在每一維度上取值的絕對值|ui|,|vi|≤10^6 (1≤i≤n)

在這裡插入圖片描述

題解思路

看完題目相信你們都會做,但是卻拿不到滿分。原因有以下兩個坑點。

結果result一定是long long型資料,因為每個 ui、vi 的絕對值為 10^6,說明中間的結果可能達到 10^12,如果不使用 long long 型資料就會造成資料溢位。從而答案不正確。

只需要用陣列記錄第一組向量 U 的資料,在第二組資料輸入的時候就可以直接判斷進行處理。這樣可以節省空間和時間,避免超時。

使用一個 U 向量的記錄型指標pointer進行輔助處理。

題解(c/c++)

#include <iostream>
using namespace std;
struct P
{
    int index,value;
};
int main() {
    int n, a, b;
    cin >> n >> a >> b;
    struct P U[a + 1];
    for (int i = 0; i < a; i++) {
        cin >> U[i].index >> U[i].value;
    }
    long long result = 0; //取值的絕對值為10^6,乘積為10^12,必須用long long型
    int pointer = 0; //U向量的記錄型指標
    int index, value;
    for (int i = 0; pointer < a && i < b; i++) {
        cin >> index >> value;
        while (pointer < a && index > U[pointer].index) pointer++;
        if (index > U[a - 1].index) break; //如果V向量輸入的index大於了U向量最大的index,後面的全是0不用考慮
        if (pointer >= a) break;    //U向量對應的資料已經計算完,後面V向量的輸入不用再考慮
        if (index == U[pointer].index) result += U[pointer++].value * value;//計算完後pointer指標增1
    }
    cout << result;
}