#20754: 測資#0#1都過不了


stardeng2945@gmail.com (天空Pixeleston)

學校 : 新北市私立竹林高級中學
編號 : 83561
來源 : [218.187.82.140]
最後登入時間 :
2022-08-10 09:27:51
e809. 1.字母排序 (Letters) -- 2019年11月TOI練習賽潛力組 | From: [218.187.80.81] | 發表日期 : 2020-02-29 19:27

測資#0#1都過不了,而且每次錯誤訊息都不一樣,我用C++,請問有無大神可幫忙解答?以下為程式碼
#include<iostream> using namespace std; int main(){ string s, S; cin >> s >> S; int A[S.length() + 100], i, j, Q, X, InBLocal = 0; int B[100]; // B[InBLocal] = contains letter Local[InBLocal] = contains Letter's Local int Local[100]; Local[0] = 0; for(i = 0; i <= S.length(); i ++){ A[i] = 0; } for(i = 0; i <= 26; i ++){ B[i] = 0; Local[i] = 0; } for(i = 0; i < S.length(); i ++){ A[(int)S[i] - 64] ++; } for(i = 0; i < s.length(); i ++){ // CBA i=0 B[InBLocal] = 3(C) Local[InBLocal] = Local[InBLocal-1] + A[3(C)] InBLocal ++; B[InBLocal] = (int)s[i] - 64; Local[InBLocal] = Local[InBLocal - 1] + A[(int)s[i] - 64]; // Local[i] means this letter contains local (Local[i-1] + 1) ~ (Local[i]) } cin >> Q; for(i = 1; i <= Q; i ++){ cin >> X; for(j = 1; j <= InBLocal; j ++){ if(X > Local[j-1] && X <= Local[j]){ // j is the key letter which needs to be output cout << (char)(B[j] + 64) << endl; } } } }
 
#20755: Re:測資#0#1都過不了


inversion (「我們所認識的可符香是個像天使的好女孩」之葉林 *Cries...)

學校 : 國立清華大學
編號 : 43537
來源 : [49.159.6.107]
最後登入時間 :
2022-05-28 19:29:12
e809. 1.字母排序 (Letters) -- 2019年11月TOI練習賽潛力組 | From: [49.158.83.43] | 發表日期 : 2020-02-29 22:49

測資#0#1都過不了,而且每次錯誤訊息都不一樣,我用C++,請問有無大神可幫忙解答?以下為程式碼
#include using namespace std; int main(){ string s, S; cin >> s >> S; int A[S.length() + 100], i, j, Q, X, InBLocal = 0; int B[100]; // B[InBLocal] = contains letter Local[InBLocal] = contains Letter's Local int Local[100]; Local[0] = 0; for(i = 0; i <= S.length(); i ++){ A[i] = 0; } for(i = 0; i <= 26; i ++){ B[i] = 0; Local[i] = 0; } for(i = 0; i < S.length(); i ++){ A[(int)S[i] - 64] ++; } for(i = 0; i < s.length(); i ++){ // CBA i=0 B[InBLocal] = 3(C) Local[InBLocal] = Local[InBLocal-1] + A[3(C)] InBLocal ++; B[InBLocal] = (int)s[i] - 64; Local[InBLocal] = Local[InBLocal - 1] + A[(int)s[i] - 64]; // Local[i] means this letter contains local (Local[i-1] + 1) ~ (Local[i]) } cin >> Q; for(i = 1; i <= Q; i ++){ cin >> X; for(j = 1; j <= InBLocal; j ++){ if(X > Local[j-1] && X <= Local[j]){ // j is the key letter which needs to be output cout << (char)(B[j] + 64) << endl; } } } }

用您的程式碼去跑範例輸入第二筆,發現會錯誤。三個的輸出皆是「Z」。再加上您說的「每次錯誤訊息都不一樣」,因此猜想是初始化錯誤或是存取錯誤的記憶體區間。

而實際測試之後,發現您的 A 陣列之初始化以及後面的用途並不吻合。

 

我猜想您的 A 陣列是用來統計字元出現的次數。可是初始化卻是用字串 S 的長度去初始化,而非 A ~ Z  26 個字母的「26」。因此,範例輸入第二筆在統計 Z 時,存取的位置為 A[26]。但是前面初始化的部分只有到 A[0] ~ A[12] 。

 

一些語法和撰寫程式習慣上的建議:

如果陣列只需使用一次的話,全 0 的初始化可以在宣告的時候達成。例如:int A[8888] = {};

該語法即是宣告一大小為 8888 個 int 的陣列,且全預設為 0 。要特定前幾個位置的話,可以寫成像是 int A[8888] = { 0, 912, 888 }; 其代表將 A[0] 設為 0 、 A[1] 設為 912 、 A[2] 設為 888 。

其他情況以此類推。

 

如果要多次的初始化,可以使用 <cstring> 標頭檔底下的 memset() 函式。假設現在 int A[123];

則可寫一列程式碼:memset(A, 0, sizeof(A)); 代表將 A 陣列的位元組(Bytes)之值全部設為 0 。如果是 memset(A, 1, sizeof(A)) 則代表將所有位元組之值設為 1 ,但這並非代表 A[0] 、 A[1] 就是 1 。

因為一個 int 由四個位元組組成,而 memset 設定的是位元組。因此,A[0] 、 A[1] 等等的值在十六進位下是 01 01 01 01 (用空白隔開,代表一個 int 中不同的位元組),其值為十進位的 16843009 。

所以用來設定極大值、極小值或是 0 比較常用。

 

雖然您有使用註解並加上幾個有意義的變數名稱。但是還不夠,例如陣列 A 就沒有被描述到,也無法從變數名稱得知用途。變數的名稱可以再多樣一點。

Local 一詞比較接近中文的「在地」、「當地」,而不是「位置」(Location,可簡寫為 Loc,但不建議)。而用途與實際意義比較接近「位置」。當然,這比較主觀,僅供參考。

還有不需要真的寫「- 64」,可以寫作「('A' - 1)」,表示字元「A」在 ASCII 編碼下之值去減 1 。免於記憶這些特定的值(雖然記得比較方便),而且程式碼的可讀性比較高。

 

以上。希望有幫助到您。

 
#20866: Re:測資#0#1都過不了


stardeng2945@gmail.com (天空Pixeleston)

學校 : 新北市私立竹林高級中學
編號 : 83561
來源 : [218.187.82.140]
最後登入時間 :
2022-08-10 09:27:51
e809. 1.字母排序 (Letters) -- 2019年11月TOI練習賽潛力組 | From: [218.187.81.70] | 發表日期 : 2020-03-14 16:54

測資#0#1都過不了,而且每次錯誤訊息都不一樣,我用C++,請問有無大神可幫忙解答?以下為程式碼
#include using namespace std; int main(){ string s, S; cin >> s >> S; int A[S.length() + 100], i, j, Q, X, InBLocal = 0; int B[100]; // B[InBLocal] = contains letter Local[InBLocal] = contains Letter's Local int Local[100]; Local[0] = 0; for(i = 0; i <= S.length(); i ++){ A[i] = 0; } for(i = 0; i <= 26; i ++){ B[i] = 0; Local[i] = 0; } for(i = 0; i < S.length(); i ++){ A[(int)S[i] - 64] ++; } for(i = 0; i < s.length(); i ++){ // CBA i=0 B[InBLocal] = 3(C) Local[InBLocal] = Local[InBLocal-1] + A[3(C)] InBLocal ++; B[InBLocal] = (int)s[i] - 64; Local[InBLocal] = Local[InBLocal - 1] + A[(int)s[i] - 64]; // Local[i] means this letter contains local (Local[i-1] + 1) ~ (Local[i]) } cin >> Q; for(i = 1; i <= Q; i ++){ cin >> X; for(j = 1; j <= InBLocal; j ++){ if(X > Local[j-1] && X <= Local[j]){ // j is the key letter which needs to be output cout << (char)(B[j] + 64) << endl; } } } }

用您的程式碼去跑範例輸入第二筆,發現會錯誤。三個的輸出皆是「Z」。再加上您說的「每次錯誤訊息都不一樣」,因此猜想是初始化錯誤或是存取錯誤的記憶體區間。

而實際測試之後,發現您的 A 陣列之初始化以及後面的用途並不吻合。

 

我猜想您的 A 陣列是用來統計字元出現的次數。可是初始化卻是用字串 S 的長度去初始化,而非 A ~ Z  26 個字母的「26」。因此,範例輸入第二筆在統計 Z 時,存取的位置為 A[26]。但是前面初始化的部分只有到 A[0] ~ A[12] 。

 

一些語法和撰寫程式習慣上的建議:

如果陣列只需使用一次的話,全 0 的初始化可以在宣告的時候達成。例如:int A[8888] = {};

該語法即是宣告一大小為 8888 個 int 的陣列,且全預設為 0 。要特定前幾個位置的話,可以寫成像是 int A[8888] = { 0, 912, 888 }; 其代表將 A[0] 設為 0 、 A[1] 設為 912 、 A[2] 設為 888 。

其他情況以此類推。

 

如果要多次的初始化,可以使用 標頭檔底下的 memset() 函式。假設現在 int A[123];

則可寫一列程式碼:memset(A, 0, sizeof(A)); 代表將 A 陣列的位元組(Bytes)之值全部設為 0 。如果是 memset(A, 1, sizeof(A)) 則代表將所有位元組之值設為 1 ,但這並非代表 A[0] 、 A[1] 就是 1 。

因為一個 int 由四個位元組組成,而 memset 設定的是位元組。因此,A[0] 、 A[1] 等等的值在十六進位下是 01 01 01 01 (用空白隔開,代表一個 int 中不同的位元組),其值為十進位的 16843009 。

所以用來設定極大值、極小值或是 0 比較常用。

 

雖然您有使用註解並加上幾個有意義的變數名稱。但是還不夠,例如陣列 A 就沒有被描述到,也無法從變數名稱得知用途。變數的名稱可以再多樣一點。

Local 一詞比較接近中文的「在地」、「當地」,而不是「位置」(Location,可簡寫為 Loc,但不建議)。而用途與實際意義比較接近「位置」。當然,這比較主觀,僅供參考。

還有不需要真的寫「- 64」,可以寫作「('A' - 1)」,表示字元「A」在 ASCII 編碼下之值去減 1 。免於記憶這些特定的值(雖然記得比較方便),而且程式碼的可讀性比較高。

 

以上。希望有幫助到您。

太感謝您的建議了,謝謝您讓我通過了這題~


 
ZeroJudge Forum