暑假資讀[1]

陳澔樂   &  數資25

介紹

  • 225
  • 班上充滿學術長(學弟加電研,還有魔方)
  • 因為想學語法所以來當講師

競賽介紹

主線任務

校內能力競賽

北市賽

全國賽

選訓營 1!

選訓營 2!

海選 or APCS

初選

亞太資奧 APIO

11人

12人

20人

10人

10人

4人

支線任務

  • APCS

  • NPSC

  • YTP

  • ISSC

  • HP codewars

目的:

好玩

升學

Online Judge

寫題目的地方

TIOJ  建中資訊社

OJDL

ZeroJudge  台灣最多人用的OJ

Codeforces 最大的 OJ

Atcoder  第二大的 OJ

CSES 裸題

CSAcademy 技巧

.....

*Codeforces 和 Atcoder 還有定期線上比賽

帳號設定

TIOJ  自己去搞

(可以用一個酷酷的motto 可用LaTex

Zerojudge 學校設建中

Codeforces Atcoder 建議現在就開

國籍設中華民國

學校設建中(注意CF上有兩個 選比較多人的

(你就可以開始電爛學長了

  • AC(Accept)
  • WA(Wrong Answer)
  • TLE(Time Limit Exceed)
  • MLE(Memory Limit Exceed)
  • RE(Runtime Error)
  • CE(Compile Error)

條件判斷

(Che is smart )==true

布林判斷式

回傳一個bool

1 == true == 真

0 == false == 假

常見運算子 == != > <
作用 等於 不等於 大於 小於
<= >= ! && ||
小於等於 大於等於
(1變0,0變1)

飯粒

1 + 2 == 3 // true
1 + 2 == 4 // false

1 + 2 != 3 // false
1 + 2 != 4 // true

!(1 && 1) // false
(0 || 1)  // true

注意事項:運算順序

字太小?

幫你整理:

<  <=  >=  >
==   !=
&&
||
=
(注意!不是布林運算子!)
()

好用東西-->

if, else, else if

if

if (條件式) {
    cout << "條件式為true時會印出這一行" << endl;
}

else

if (條件式) {
    cout << "條件式為true時會印出這一行" << endl;
} else {
    cout << "條件式為false時會印出這一行" << endl;
}

else if

// A, B 皆為條件式
if (A) {
    cout << "A 為 true" << endl;
} else if (B) {
    cout << "A 為 false 但是 B 為 true" << endl;
} else {
    cout << "A、B 都是 false" << endl;
}

經典範例

#include <iostream>
using namespace std;
int main() {
    int score; cin >> score;
    if (score >= 80) cout << "AaW不可能是電神一定是成績改錯了\n";
    else if (score >= 60) 
        cout << "好扯竟然有及格\n"; // 注意:以上兩種寫法if只會包含一行
    else if (score >= 40) {
        cout << "快去準備補考\n";
    }
    else {
        cout << "沒救了QAQ\n";
    }
}

AaW的物理成績實在太爛了,面臨補考邊緣。已知建中學期總成績60分以上為及格,40~59分要參加補考,39分以下就被死當了QAQ。又這一次物理老師成績打法心狠手辣,如果有辦法拿到80分以上就算是大電神。

但是AaW小學數學沒有學好,請幫他判斷他的成績算是哪個範圍呢?

switch case

switch(變數/式子){
    case 可能1: //符合可能1
        做事;
        break; // 沒有break會繼續執行!!!
    case 可能2: //符合可能2
        做事;
        break;
    default: //上面的可能都沒符合
        做事;
        break;
}

switch case

int a;
cin >> a;
switch(a){
    case 100: 
        cout << "a==100" << endl;
        break; 
    case 200: 
        cout << "a==200" << endl;
        // 沒有break
    case 300:
        cout << "a==200 or a==300" << endl;
        break;
    default: //上面的可能都沒符合
        cout << "a不是100, 200, 300" << endl;
        break;
}

三元運算子

A? x: y

當A為true回傳x

否則回傳y

int a = 12;
int b = ((a==12)? 23: 24); // b == 23
int c = ((a==14)? 33: 66); // c == 66

題目

有多筆測資部分等等會解釋要怎麼處理

題解

#include <iostream>
using namespace std;

signed main(){
    long long a, b, c;
    while(cin >> a >> b >> c) {
        if (a+b>c && b+c>a && a+c>b) cout << "SAFE"<<endl;
        else cout << "BYE" << endl;
    }
    return 0;
}

任兩邊和大於第三邊

#include <iostream>
using namespace std;

signed main(){
    int a, b, c;
    cin >> a >> b >> c;
    if(a == b && b == c && a * b * c != 0) cout << "both";
    else if(a * c == b * b && a * b * c != 0) cout << "geometric";
    else if(a + c == b + b) cout << "arithmetic";
    else cout << "normal";
    return 0;
}

要注意等比級數部分,不可以有0

loops

迴圈

人生啊

用途

直接看例題:

 

 

No Judge:

給一個正整數N

輸出N個"*"

CODE

#include<bits/stdc++.h>
using namespace std;



int main(){
	int n;cin>>n;
	for(int i=0;i<n;i++){
		cout<<"*";
	}

	return 0;
}

迴圈

用途

重複某件事情

兩大迴圈

for

for (起始; 終止條件; 更新) {
  // 注意是用分號隔開
  // do something...
}

範例

輸出從0 ~ 9

#include <iostream>
using namespace std;

signed main(){
    int n = 10;
    for (int i = 0; i < n; ++i) {
        cout << i << " ";
    }
    cout << endl;
    return 0;
}

範例

輸出從1 ~ 10

0 1 2 3 4 5 6 7 8 9
#include <iostream>
using namespace std;

signed main(){
    int n = 10;
    for (int i = 1; i <= n; ++i) {
        cout << i << " ";
    }
    cout << endl;
    return 0;
}
1 2 3 4 5 6 7 8 9 10

二維迴圈

#include <iostream>
using namespace std;

signed main(){
    for (int i = 1; i <= 9; ++i) {
        for (int j = 1; j <= 9; ++j) {
            cout << i*j << " ";
        }
        cout << endl;
    }
    return 0;
}
1 2 3 4 5 6 7 8 9 
2 4 6 8 10 12 14 16 18 
3 6 9 12 15 18 21 24 27 
4 8 12 16 20 24 28 32 36 
5 10 15 20 25 30 35 40 45 
6 12 18 24 30 36 42 48 54 
7 14 21 28 35 42 49 56 63 
8 16 24 32 40 48 56 64 72 
9 18 27 36 45 54 63 72 81 

while迴圈

while (A) { // A 為一個boolean expression
    // A == true
    // do something
}
// A == false

當表示式為真,不斷重複執行

和if的差別

while 內會一直重複,if 只會執行一次

飯粒

#include <iostream>
using namespace std;

signed main(){
    int a = 12;
    while (a < 23) {
        cout << a << " ";
        a = a + 3;
    }
    cout << endl <<  "after while: a=" << a << endl;
    return 0;
}
12 15 18 21
after while: a=24

同場加映:do while

please enter password:
wrong password
please enter password:
wrong password
please enter password:
password correct

管你三七二十一,先做再說

至少會被執行一次!

#include <iostream>
#include <string>
using namespace std;
int main() {
    string password = "aawsoweak";
    string userinput;
    do {
        cout << "please enter password: ";
        cin >> userinput;
        if (userinput != password) cout << "wrong password\n";
    } while (userinput != password);
    cout << "password correct\n";
}
please enter password:
password correct
 brineorz
 
 8wcp
 
 aawsoweak
 aawsoweak

無限迴圈

while (true) {

   // do sth

}

這樣不就永遠卡住了嗎?怎麼辦?

卡在廁所迴圈的救星

break

直接跳出去

while (條件) {
    if (想要提早跳出) {
        break;
    }
    // do sth
}

// break 完會跑到這邊

只想跳過一次怎麼辦?

continue

跳到下一次迴圈

#include <iostream>
using namespace std;
int main() {
	for (int i = 1; i <= 5; ++i) {
        if (i == 3) {
            cout << "continue executed!\n";
            continue;
        }
        cout << "i = " << i << endl;
    }
}
i = 1
i = 2
continue executed!
i = 4
i = 5

continue vs break

while (/*...*/) { // continue 會回到這裡
    if (sth) continue;
    if (sth) break;
    // do sth
}
// break 會直接跳出到這裡

補坑

多筆測資讀到EOF?

例子:zj a004

int n;
while (cin >> n) {
    // do sth
}

手動輸入測試時,可以用ctrl + D 代替EOF

補坑

多筆測資讀到n==0?

int n;
cin >> n;
while (n != 0) {
    // do sth
    cin >> n;
}
int n;
while (cin>>n && n) {
   //do sth
}

題目

while 和 for 都會用到喔!

更多例題

Array

Storing a lot of data

Problem A-1

You are given three numbers, find the largest one among them.

#include <iostream>

using namespace std;

int main() {
    int a, b, c;
    cin >> a >> b >> c;
    if (a > b) {
    	if (a > c) {
            cout << a;
        } else {
            cout << c;
        }
    } else {
    	if (b > c) {
            cout << b;
        } else {
            cout << c;
        }
    }
}

Problem A-1

The last appoach is terrible, don't follow

#include <iostream>

using namespace std;

int main() {
    int a, b, c;
    cin >> a >> b >> c;
    int max = -420;
    if (a > max) {
        max = a;
    }
    if (b > max) {
        max = b;
    }
    if (c > max) {
        max = c;
    }
}

Problem A-2

You are given 100 numbers, find the largest one.

#include <iostream>

using namespace std;

int main() {
    int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30, a31, a32, a33, a34, a35, a36, a37, a38, a39, a40, a41, a42, a43, a44, a45, a46, a47, a48, a49, a50, a51, a52, a53, a54, a55, a56, a57, a58, a59, a60, a61, a62, a63, a64, a65, a66, a67, a68, a69, a70, a71, a72, a73, a74, a75, a76, a77, a78, a79, a80, a81, a82, a83, a84, a85, a86, a87, a88, a89, a90, a91, a92, a93, a94, a95, a96, a97, a98, a99, a100; 
    cin >> a1 >> a2 >> a3 >> a4 >> a5 >> a6 >> a7 >> a8 >> a9 >> a10 >> a11 >> a12 >> a13 >> a14 >> a15 >> a16 >> a17 >> a18 >> a19 >> a20 >> a21 >> a22 >> a23 >> a24 >> a25 >> a26 >> a27 >> a28 >> a29 >> a30 >> a31 >> a32 >> a33 >> a34 >> a35 >> a36 >> a37 >> a38 >> a39 >> a40 >> a41 >> a42 >> a43 >> a44 >> a45 >> a46 >> a47 >> a48 >> a49 >> a50 >> a51 >> a52 >> a53 >> a54 >> a55 >> a56 >> a57 >> a58 >> a59 >> a60 >> a61 >> a62 >> a63 >> a64 >> a65 >> a66 >> a67 >> a68 >> a69 >> a70 >> a71 >> a72 >> a73 >> a74 >> a75 >> a76 >> a77 >> a78 >> a79 >> a80 >> a81 >> a82 >> a83 >> a84 >> a85 >> a86 >> a87 >> a88 >> a89 >> a90 >> a91 >> a92 >> a93 >> a94 >> a95 >> a96 >> a97 >> a98 >> a99 >> a100;
    int max = 0;
    if (a1 > max) {
        max = a1;
    }
    if (a2 > max) {
        max = a2;
    }
    if (a3 > max) {
        max = a3;
    }
    if (a4 > max) {
        max = a4;
    }
    if (a5 > max) {
        max = a5;
    }
    if (a6 > max) {
        max = a6;
    }
    if (a7 > max) {
        max = a7;
    }
    if (a8 > max) {
        max = a8;
    }
    if (a9 > max) {
        max = a9;
    }
    if (a10 > max) {
        max = a10;
    }
    if (a11 > max) {
        max = a11;
    }
    if (a12 > max) {
        max = a12;
    }
    if (a13 > max) {
        max = a13;
    }
    if (a14 > max) {
        max = a14;
    }
    if (a15 > max) {
        max = a15;
    }
    if (a16 > max) {
        max = a16;
    }
    if (a17 > max) {
        max = a17;
    }
    if (a18 > max) {
        max = a18;
    }
    if (a19 > max) {
        max = a19;
    }
    if (a20 > max) {
        max = a20;
    }
    if (a21 > max) {
        max = a21;
    }
    if (a22 > max) {
        max = a22;
    }
    if (a23 > max) {
        max = a23;
    }
    if (a24 > max) {
        max = a24;
    }
    if (a25 > max) {
        max = a25;
    }
    if (a26 > max) {
        max = a26;
    }
    if (a27 > max) {
        max = a27;
    }
    if (a28 > max) {
        max = a28;
    }
    if (a29 > max) {
        max = a29;
    }
    if (a30 > max) {
        max = a30;
    }
    if (a31 > max) {
        max = a31;
    }
    if (a32 > max) {
        max = a32;
    }
    if (a33 > max) {
        max = a33;
    }
    if (a34 > max) {
        max = a34;
    }
    if (a35 > max) {
        max = a35;
    }
    if (a36 > max) {
        max = a36;
    }
    if (a37 > max) {
        max = a37;
    }
    if (a38 > max) {
        max = a38;
    }
    if (a39 > max) {
        max = a39;
    }
    if (a40 > max) {
        max = a40;
    }
    if (a41 > max) {
        max = a41;
    }
    if (a42 > max) {
        max = a42;
    }
    if (a43 > max) {
        max = a43;
    }
    if (a44 > max) {
        max = a44;
    }
    if (a45 > max) {
        max = a45;
    }
    if (a46 > max) {
        max = a46;
    }
    if (a47 > max) {
        max = a47;
    }
    if (a48 > max) {
        max = a48;
    }
    if (a49 > max) {
        max = a49;
    }
    if (a50 > max) {
        max = a50;
    }
    if (a51 > max) {
        max = a51;
    }
    if (a52 > max) {
        max = a52;
    }
    if (a53 > max) {
        max = a53;
    }
    if (a54 > max) {
        max = a54;
    }
    if (a55 > max) {
        max = a55;
    }
    if (a56 > max) {
        max = a56;
    }
    if (a57 > max) {
        max = a57;
    }
    if (a58 > max) {
        max = a58;
    }
    if (a59 > max) {
        max = a59;
    }
    if (a60 > max) {
        max = a60;
    }
    if (a61 > max) {
        max = a61;
    }
    if (a62 > max) {
        max = a62;
    }
    if (a63 > max) {
        max = a63;
    }
    if (a64 > max) {
        max = a64;
    }
    if (a65 > max) {
        max = a65;
    }
    if (a66 > max) {
        max = a66;
    }
    if (a67 > max) {
        max = a67;
    }
    if (a68 > max) {
        max = a68;
    }
    if (a69 > max) {
        max = a69;
    }
    if (a70 > max) {
        max = a70;
    }
    if (a71 > max) {
        max = a71;
    }
    if (a72 > max) {
        max = a72;
    }
    if (a73 > max) {
        max = a73;
    }
    if (a74 > max) {
        max = a74;
    }
    if (a75 > max) {
        max = a75;
    }
    if (a76 > max) {
        max = a76;
    }
    if (a77 > max) {
        max = a77;
    }
    if (a78 > max) {
        max = a78;
    }
    if (a79 > max) {
        max = a79;
    }
    if (a80 > max) {
        max = a80;
    }
    if (a81 > max) {
        max = a81;
    }
    if (a82 > max) {
        max = a82;
    }
    if (a83 > max) {
        max = a83;
    }
    if (a84 > max) {
        max = a84;
    }
    if (a85 > max) {
        max = a85;
    }
    if (a86 > max) {
        max = a86;
    }
    if (a87 > max) {
        max = a87;
    }
    if (a88 > max) {
        max = a88;
    }
    if (a89 > max) {
        max = a89;
    }
    if (a90 > max) {
        max = a90;
    }
    if (a91 > max) {
        max = a91;
    }
    if (a92 > max) {
        max = a92;
    }
    if (a93 > max) {
        max = a93;
    }
    if (a94 > max) {
        max = a94;
    }
    if (a95 > max) {
        max = a95;
    }
    if (a96 > max) {
        max = a96;
    }
    if (a97 > max) {
        max = a97;
    }
    if (a98 > max) {
        max = a98;
    }
    if (a99 > max) {
        max = a99;
    }
    if (a100 > max) {
        max = a100;
    }
    
    cout << max << '\n';
}

Problem A-3

You are given 1000000 numbers, find the largest one.

WTF no

Problem A-3

#include <iostream>

using namespace std;

int main() {
    int a[100000];
    for (int i = 0; i < 100000; i++) {
        cin >> a[i];
    }

    int max = 0;
    for (int i = 0; i < 100000; i++) {
        if (a[i] > max) max = a[i];
    }
    
    cout << max << '\n';
}

Simpler right?

Initializing an array

#include <iostream>

using namespace std;

int main() {
    int a[] = {0,1,2,3,4,5,6,7,8,9};
    int b[10] = {0,1,2,3,4,5,6,7,8,9};
    int c[10] = {0};

    
    int d[10];
    cout << d[4] << '\n'; // what will happen here?

    int e[] = {0};
}

multi-dimensional array

#include <iostream>

using namespace std;

int main() {
    int twoD[3][9];
    int threeD[4][20][69];
    int fourD[7][1][2][2];
    // ...
}

variable-sized array

#include <iostream>

using namespace std;

int main() {
    int length;
    cin >> length;
    
    int arr[length];

    for (int i = 0; i < length; i++) {
        cin >> arr[i];
    }

    for (int i = 1; i < length; i++) {
        arr[i] += arr[i - 1];
    }

    length = 800;
    cout << arr[420] << '\n'; // what will happen here?
}

Array with uniform initial value

#include <iostream>

using namespace std;

int main() {
    int length, value;
    cin >> length >> value;
    
    int arr[length] = {value};

    for (int i = 0; i < length; i++) {
        cout << arr[i] << '\n';
    }
}

Doesn't work, does it?

Array with uniform initial value

#include <iostream>

using namespace std;

int main() {
    int length, value;
    cin >> length >> value;
    
    int arr[length];

    for (int i = 0; i < length; i++) {
        arr[i] = value;
    }
}

bUT tHiS lOoKs LaMe!!!11!111!!

A better array

#include <iostream>
#include <vector>

using namespace std;

int main() {
    int length, value;
    cin >> length >> value;
    
    vector<int> arr(length, value);

    for (int i = 0; i < length; i++) {
        cout << arr[i] << '\n';
    }
}

Fabulous!

vector vs. array

#include <iostream>
#include <vector>

using namespace std;

int main() {
    int a1[] = {1, 2, 3};
    vector<int> v1_1 = {1, 2, 3};
    vector<int> v1_2{1, 2, 3};

    int a2[100];
    vector<int> v2(100);

    int a3[5] = {1, 1, 1, 1, 1};
    vector<int> v3(5, 1);
}

simple tools to change a vector

#include <iostream>
#include <vector>

using namespace std;

int main() {
    vector<int> v;
    v.resize(10);
    for (int i = 0; i < 10; i++) {
        cout << v[i] << '\n';
    }
    v.resize(20, 12);
    for (int i = 0; i < 20; i++) {
        cout << v[i] << '\n';
    }
    v.resize(3);
    for (int i = 0; i < 3; i++) {
        cout << v[i] << '\n';
    }
    v.assign(6, 9);
    for (int i = 0; i < 6; i++) {
        cout << v[i] << '\n';
    }

    v = {1, 3, 2};

    cout << v.size() << '\n';

    cout << v.front(); // == v[0]
    cout << v.back(); // == v[v.size() - 1]

    v.pop_back();
    cout << v.size() << '\n';
    v.push_back(9);
    cout << v.back() << '\n';
}

if i were hated by you

#include <iostream>
#include <vector>

using namespace std;

int main() {
    vector<int> v(10, 1);
    for (int i = 1; i < v.size(); i++) {
        v[i] += v[i - 1];
    }
    
    // for (int i = 0; i < v.size(); i++)
    for (int& n: v) {
        cout << n << '\n';
    }
}

multi-dimensional vector

#include <iostream>
#include <vector>

using namespace std;

int main() {
    vector< vector<int> > ddv1;
    vector<int> ddv2[100];
}

How to initialize?

#include <iostream>
#include <vector>

using namespace std;

int main() {
    vector< vector<int> > ddv1(100, vector<int>(69, 34));

    vector<int> ddv2[100];
    for (auto& v: ddv2) {
        v.assign(69, 34);
    }
}

That's it!

More detailed syntax and usage will be in the future lessons

例題

比較難的例題

複雜度

這段程式好複雜喔??

對於兩個程式,我要比較誰更好一點

那,什麼是好?

  • ​​時間迅雷不及掩耳
  • 少少的空間

  • 正確率高
  • 打起來方便快速

比賽中關注前兩個居多

  • Time Complexity
  • Space Complexity

複雜度就是拿來衡量演算法的時空效率

怎麼測量???

實測當然最準

但這樣我們會浪費時間寫慢的程式碼

寫之前我只需要估計不就好了?

複雜度記法

有很多種標準,通常我們會看O-notation

代表一個演算法的時間上界

O(f(n)),代表演算法因為n的時空成長率不比f(n)慢

原則

一些栗子

N^2+5 ∈ O(N^2)\\ N^3+2N^2 ∈ O(N^3)\\ N+logN ∈ O(N)\\ NlogN + 5N ∈ O(NlogN)\\ 3^N+N^{1000} ∈ O(3^N)\\ N! + 2^N ∈ O(N!)\\

常見複雜度量級

空間複雜度也是一樣概念

 

看一些code

MINIMAL

找最大值

#include <bits/stdc++.h>
using namespace std;

int main() {
    int n; cin>>n;
    int arr[n];
    
    //input the elements in the array
    
    int maxn = -1;
    
    for (int i = 0; i < n; ++i) {//find the max element
    	maxn = max(maxn,arr[i]);
    }
    
    cout<<maxn<<endl;
    return 0;
}

Time complexity : O(n)

MINIMAL

插入排序

void insertion_sort(vector <int> &arr) {
    for (int i = 0; i < n-1; ++i) {
        int minnum = arr[i];
        int index = i;
        for (int j = i+1; j < n; ++j) {
            if (minnum > arr[j]) {
                index = j;
                minnum = arr[j];
            }
        }
        swap(arr[i],arr[index]);
    }
}

Best case:O(n)

Worst case:O(n^2)

Complexity:O(n^2)

均攤複雜度

  • 平常都是一樣,但是某些情況會不同
  • vector的push_back
  • 平常O(1),做n次偶爾O(n)
  • 阿那平均還是O(1)嘛

平均??

  • 假設我們平常插入是O(1)
  • 做n次插入時有一次是O(n)
  • 即插入n個元素,做了n量級的操作次數
  • 均攤下來做一次插入的時間還是O(1)

暑假資讀

By Willy Chan

暑假資讀

  • 427