Introduction to C++ and Algorithm

因為講師比較弱 我今天可能會講得很簡略

因為 boron 太強 想學難一點的東西可以參考 boron 的暑訓簡報

About C++

About C++

  • 編譯型、中階程式語言
  • 不需要直接跟機器溝通
  • 但是要自己分配記憶體
  • 有豐富的函式庫 (STL)
  • 適合用來打演算法比賽

C++ 是什麼

About C++

編譯型程式語言

和 Python、Javascript 等語言不同

要先把程式碼編譯成機械碼,接下來再拿機械碼來跑

About C++

寫 C++ 的工具

1. VSCode

2. OnlineGDB

3. Code::Blocks

對新手友善,但是很難用

最推薦用這個

About C++

CP Helper

非常推這個擴充

對演算法題目來說特別好用

Competitive Programming

Competitive Programming

什麼是演算法

  • 簡單來說,就是執行任務的思路方法
  • 像是大家最常聽到的推薦算法
    就是透過演算法去計算並且推送內容
  • 這堂小社會從基礎內容開始講起
    並且講到關於演算法競賽的內容

Competitive Programming

關於演算法競賽和演算法題目

  • 給你一些資訊,請根據題目要求回答正確的答案
  • 不是要你真的寫出一個實用的東西
  • 只要能夠回答正確答案都可以
  • 訓練思考能力和知道多少怪東西和通靈能力
  • 刷題還可以找工作

偷 from keaucucal

Judge System

  • 寫完扣以後要上傳到評測系統 (Judge)
  • 評測系統會幫你做好編譯&執行&測試
  • 比賽的時候會用他來計分

Competitive Programming

一個讓你練習程式設計與演算法的地方

會在後端有個伺服器執行你上傳的程式

對於特定的題目會有特定的輸入與輸出

如果你的程式輸入後的輸出與標準一樣

就會得到AC的結果la欸我字數都一樣欸

- by 一四學術 世宗

Results

基本上可能有以下幾個:

Competitive Programming

Verdict Full Name Meaning
AC Accecpted 你通過了
WA Wrong Answer 你錯了
TLE Time Limit Exceeded 你超時了
RE Runtime Error 你亂做事
SIG Runtime Error (Killed By Signal) 你對記憶體亂做事
MLE Memory Limit Exceeded 記憶體存不下了
CE Compile Error 你扣亂寫

Online Judge

Competitive Programming

常常辦線上賽的地方,目前最多人用的 OJ

也是常常辦線上賽,第二多人用的 OJ

題目品質很好的題庫

建中校隊的 OJ,目前全台灣最好的 OJ,有很多歷屆題目

Forked from TIOJ,是本社團的 OJ,上面有很多好題目和正向晴出的怪題

Hello, World

Hello, World

一份 C++ 程式

#include <iostream>                      // 引入函式庫
using namespace std;                     // 使用命名空間

int main() {                             // 主函式
	cout << "Hello, World !" << endl;    // 說 Hello, World !
    return 0;                            // 結束整個程式
}

一份 C++ 的扣需要包含一個主函式  main()

整個程式碼會從 main() 開始跑

大括號則是代表程式碼區塊,裡面的程式碼屬於 main() 區塊

C++ 是用分號分隔每個敘述,所以記得加分號

Hello, World

Basics

Basics

Integer

int a = 1;
int b = 2, c = 3;
a = 4;

變數 = 一個儲存資料的箱子

C++ 需要固定箱子裡的內容

例如 int 是大小有限制的整數

我可以用指定符號 ( 一個等於 = , 讀作設為) 來給變數一個值

也可以把箱子裡的東西拿出來

先來個範例

Read & Write

#include <iostream>
using namespace std;

int main() {
	int x;
    cin >> x;
    cout << x << endl;
    return 0;
}

c in 和 c out

全名 std::cin 和 std::cout (using namespace std)

用資料流的想法 箭頭指向流的方向

Basics

一次讀兩個?

Read & Write

#include <iostream>
using namespace std;

int main() {
	int a, b;
    cin >> a >> b;
    cout << a + b << endl;
    return 0;
}

Basics

End of Line

cout << endl;    // 換行

這是一個安全的換行

但是他速度偏慢

在比速度的競賽程式中,通常用下面這個換行

cout << '\n';    // 換行

這樣做的壞處是他不是及時的輸出

只有在程式結束時可以看到他輸出的結果

Basics

Variables

&

Operators

Variables & Operators

Operators

Operator Name Example
+ plus 加 1 + 2 -> 3
- minus 減 2 - 1 -> 1
* multiply 乘 3 * 4 -> 12
/ divide 除 4 / 2 -> 2

所有的運算都要注意變數類型

否則可能發生數字炸掉或整數除法等問題

記得先乘除後加減,或是順序可以用小括號分隔

Variables & Operators

Variable Types

Type Item
int
unsigned
long long
unsigned long long
bool 0 (false) or 1 (true)
float 小數 精度6~7位
double 小數 精度15~16位
char 一個字元 (Character)
string 字串 (多個字元)

\(-2^{31} \sim 2^{31} - 1\) 的整數

\(0 \sim 2^{32} - 1\) 非負整數

\(-2^{63} \sim 2^{63} - 1\) 的整數

\(0 \sim 2^{64} - 1\) 非負整數

Variables & Operators

Variables & Operators

Precision

int a = 5, b = 2;
cout << a / b << '\n';  // Output : 2
int a = 1000000000000000000;
cout << a << '\n';  // Output : -1486618624
float a = 1, b = 3;
cout << a / b << '\n';  // Output : 0.333333

Conditionals

Conditionals

Comparators

Operator Name Example
> greater 大於 2 > 1 -> true
< less 小於 2 < 1 -> false
>= 大於等於 2 >= 1 -> true
<= 小於等於 2 <= 1 -> false
== equal 等於 2 == 1 -> false
!= 不等於 2 != 1 -> true
! not 否 !false -> true
&& and 而且 true && false -> false
|| or 或者 true || false -> true
^ xor 異或 (不相等) true ^ false -> true

Conditionals

If & Else

int a = 1, b = 2;
if (a == b) {                                // 如果括號裡面為真 (a == b)
	cout << "a equals to b" << '\n';         // 說 a 等於 b
} else {                                     // 否則 (這個區塊不一定要寫)
	cout << "a is different to b" << '\n';   // 說 a 不等於 b
}

Output : a is different to b

int a = 123456;
if (a % 2 == 1) {                 // a 除以 2 的餘數是 1
	cout << "a is odd" << '\n';   // a 是奇數
} else {                          // 否則
	cout << "a is even" << '\n';  // a 是偶數
}

如果 ( ) 裡為真,就執行第一個區塊,否則就是 else 區塊

Conditionals

Ternary Operation

condition? a : b // 如果 condition 為真就是 a, 否則是 b
int a = 123456;
cout << "a is " << (  (a % 2 == 1)? "odd" : "even"  ) << '\n';   // 判斷奇偶

Conditionals

Else if

int grade;
cin >> grade;
if (grade >= 90) {
    cout << "A" << '\n';
} else if (grade >= 80) {
    cout << "B" << '\n';
} else if (grade >= 70) {
    cout << "C" << '\n';
} else if (grade >= 60) {
    cout << "D" << '\n';
} else {
    cout << "E" << '\n';
}

否則還有如果

Conditionals

SWITCH CASE

int type;
cin >> type;

switch (type) {
case 1:         // if (type == 1)
	cout << "This is type 1" << '\n';
    break;      // 記得加 break
case 2:         // else if (type == 2)
	cout << "This is type 2" << '\n';
  	break;
case 3:         // else if (type == 3)
	cout << "This is type 3" << '\n';
    break;
default:         // else
	cout << "Other cases" << '\n';
	break;
}

用來做分類

Conditionals

SWITCH CASE

Arrays

&

Loops

Arrays & Loops

一串的變數 (箱子)

Array

1 5 2 8 9

0

1

2

3

4

位址 (index)

值 (value)

要注意電腦是使用 0-based

就是要取出陣列第一個要用 arr[0], 第二個用 arr[1] ...

Arrays & Loops

Array

int arr[5] = {1, 5, 2, 8, 9};  // 一串 int
cout << arr[0] << ' ';
cout << arr[1] << ' ';
cout << arr[2] << ' ';
cout << arr[3] << ' ';
cout << arr[4] << '\n';
1 5 2 8 9

0

1

2

3

4

位址 (index)

值 (value)

Arrays & Loops

Array

int arr[5] = {1, 5, 2, 8, 9};
arr[0] = 100;
cout << arr[0] << ' ';
cout << arr[1] << ' ';
cout << arr[2] << ' ';
cout << arr[3] << ' ';
cout << arr[4] << '\n';

可以修改

int arr[5]; // 長度為 5

cin >> arr[0] >> arr[1] >> arr[2] >> arr[3] >> arr[4] >> arr[5];

也可以輸入到陣列

Arrays & Loops

For Loops

一種重複執行的工具

通常會帶有一個變數,然後透過這個變數來判斷跑的次數

for (int i = 0; i < 5; i++) {
	cout << i << '\n';
}

用法是 for(開始前要做的事情; 如果為真就往下跑; 每次跑完都要做的事)

我們先開了一個變數 i, 設定 i = 0;

i < 5 為真,往下跑

cout << i << '\n'; 輸出 0

接下來做 i++;  (i = i + 1 的簡寫,注意一個等於是設為)

依此類推...

直到 i == 5, i < 5 為假, 退出迴圈

Arrays & Loops

For Loops

int arr[5] = {1, 5, 2, 8, 9};
for (int i = 0; i < 5; i++) {
	cout << arr[i] << '\n';
}

用法是 for(開始前要做的事情; 如果為真就往下跑; 每次跑完都要做的事)

實際用途之一是可以印出陣列所有的值

Arrays & Loops

While Loops

分享一個經典的 \(3n + 1\) 問題

給你一個數字 \(n\)

如果他是奇數, 把他乘以 \(3\) 再加 \(1\)

如果他是偶數, 把他除以 \(2\)

已知他一定會變成 \(1\) (但是未被證明), 輸出數字在變成 \(1\) 之前的過程

例如 : \(3 \rightarrow 10 \rightarrow 5 \rightarrow 16 \rightarrow 8 \rightarrow 4 \rightarrow 2 \rightarrow 1\)

Arrays & Loops

While Loops

long long n; cin >> n;
while (n != 1) {        // n != 1 就往下跑
    cout << n << ' ';   // 輸出 n 和一個空白
    if (n % 2 == 1) {   // n 是奇數
        n = 3 * n + 1;  // 3n + 1
    } else {            // n 是偶數
        n = n / 2;      // 除以 2
    }
}
cout << 1 << '\n';      // 結束補一個 1

// 這份 code 有一筆測試資料會是錯的,你能找出是哪一筆嗎

用法是 while(如果為真就往下跑)

如果不確定重複的次數?

有另外一種工具,就是重複...如果括號裡為真

Arrays & Loops

Do While

long long n; cin >> n;
do {                    // n != 1 就往下跑
    cout << n << ' ';   // 輸出 n 和一個空白
    if (n % 2 == 1) {   // n 是奇數
        n = 3 * n + 1;  // 3n + 1
    } else {            // n 是偶數
        n = n / 2;      // 除以 2
    }
} while (n != 1) ;      // 記得加分號
cout << 1 << '\n';

先做事再判條件

Arrays & Loops

Do While

Arrays & Loops

Continue

for (int i = 0; i < 5 ; i++) {
    cout << "Hmm" << '\n';
    if (i == 3) continue;
    cout << "i = " << i << '\n';
}

省略掉一次迴圈中接續的內容

Arrays & Loops

Break

for (int i = 0; i < 5 ; i++) {
    cout << "Hmm" << '\n';
    if (i == 3) break;
    cout << "i = " << i << '\n';
}

跳出迴圈

Arrays & Loops

如何對記憶體亂做事

int a[5] = {1, 2, 3, 4, 5};
cout << a[6] << '\n';  //???
cout << a[5] << '\n';  //注意這樣會炸,因為陣列是 0-based

int b = [1000000000000000000]; //???

Practices

進階題

CSES 1754 (我當時也想不到)

Thanks

Intro to CPP

By Roy Chuang

Intro to CPP

  • 160