# 競プロ班 講義第四回 ## 復習 文字列や配列、STLの関数などにまつわる重要な文法を復習しておきましょう。 - **注意** APG4bでは、文字列や配列のi番目の要素へのアクセスに```.at(i)```を用いていますが、ほとんどのc++競プロerはタイプ数の少なさから```.at(i)```でなく```[i]```を用います。 この講義でもi番目の要素へのアクセスには```[i]```を用います - **文字列** string型の基本操作 ```cpp string s = "Hello"; //文字列の長さを取得 cout << s.size() << endl; // 5 //文字列のi文字目を取得 cout << s[0] << " " << s[3] << endl; // H l // 文字列の一部を書き換えるときや比較をするときはchar型(文字型)を用いる s[0] = 'M'; cout << s << endl; // Mello cout << (s[0] == 'M') << endl; // true //for文との組み合わせ for (int i = 0; i < s.size(); i++) { cout << s[i] << " "; // M e l l o } // 文字列同士の比較 string s1 = "ABC"; string s2 = "XY"; cout << (s1 < s2) << endl; // true // 文字列の連結 string hello = "Hello"; cout << hello + ", world!" << endl; // Hello, world! hello += ", AtCoder!"; cout << hello << endl; // Hello, AtCoder! ``` - **配列** ```cpp int N; vector<int> vec(N); //配列の宣言 for (int i = 0; i < N; i++) { cin >> vec[i]; //配列で入力を受け取る } cout << vec[0] << endl; //配列の要素を出力 vec.push_back(1); //配列の末尾に要素を追加 ``` - **STLの関数** ```cpp int a = 10, b = 5; cout << min(a, b) << endl; // 5 cout << max(a, b) << endl; // 10 swap(a, b); // aとbの値を交換 cout << a << " " << b << endl; // 5 10 string s = "Hello"; swap(s[0], s[2]); // char型に対してもswapは使える vector<int> vec = {1, 5, 3}; reverse(vec.begin(), vec.end()); // {3, 5, 1} vector<int> V = {2, 5, 2, 1}; sort(V.begin(), V.end()); // {1, 2, 2, 5} ``` ## 演習 いくつか演習問題を解きましょう! 今回紹介している問題には難しい問題も多いです。少し考えてわからなければ解説をみるのが良いと思います。ただし解説を見る場合はしっかりと内容を理解した上で自分で実装しきるのが望ましいです。 講義中で全ての問題を扱うことはできないので、講義で扱えなかった問題は良ければ講義後に解いてみてください! よく使う知識や考え方が学べる教育的な問題を選んでいるつもりです [B - Maritozzo](https://atcoder.jp/contests/abc219/tasks/abc219_b) 文字列の基本的な操作に慣れましょう [B - Can you buy them all?](https://atcoder.jp/contests/abc209/tasks/abc209_b) 配列の基本的な操作に慣れましょう [B - Qualification Contest](https://atcoder.jp/contests/abc288/tasks/abc288_b) ソートを使いましょう [B - Postal Card](https://atcoder.jp/contests/abc287/tasks/abc287_b) 配列を使った全探索です。 部分文字列を得る関数substrを用いると良いです。```s.substr(開始のindex, 部分文字列の長さ)```のように使います ``` string s = "Hello"; s.substr(1, 3) // ell ``` [A - Pawn on a Grid](https://atcoder.jp/contests/abc280/tasks/abc280_a) 2次元配列を用いる問題です。2次元配列に慣れましょう [B - Bombs](https://atcoder.jp/contests/abc295/tasks/abc295_b) 一つ前の問題と同様に2次元配列を用いる問題です --- [B - typo](https://atcoder.jp/contests/abc221/tasks/abc221_b) swap関数を使いましょう [B - At Most 3 (Judge ver.)](https://atcoder.jp/contests/abc251/tasks/abc251_b) 全探索 [B - Longest Segment](https://atcoder.jp/contests/abc234/tasks/abc234_b) 全探索+max関数+sqrt関数 sqrt(x)で$\sqrt x$の値を得ることができます。sqrt関数を用いるにはcmathライブラリをインクルードします ```cpp #include <cmath> ``` [A - First Player](https://atcoder.jp/contests/abc304/tasks/abc304_a) min関数を使いましょう。難しめ [C - Max MEX](https://atcoder.jp/contests/abc290/tasks/abc290_c) 多少考察が必要かもしれません。難しめ [C - Cash Register](https://atcoder.jp/contests/abc283/tasks/abc283_c) 非常に大きい数字(桁が100桁以上など)は文字列型で扱うと良い場合があります。 [C - AtCoder Cards](https://atcoder.jp/contests/abc301/tasks/abc301_c) 難しめです。多少考察が必要かもしれません。難しめ ## 数値型 APG4bの[Y - 3.01.数値型](https://atcoder.jp/contests/apg4b/tasks/APG4b_y)の中で重要な内容について紹介します。 - long long型 今までは整数を扱う際にint型を使ってきましたが、int型が表せる範囲には限りがあります。具体的には、int型は$-2^{31}$以上$2^{31}$未満、つまり-2147483648以上2147483647以下の整数のみ表すことができます。 int型で表せる範囲を超える整数をint型で扱おうとするとオーバーフローが発生し、正しい値を保持できません。 以下のコードを実行すると、オーバーフローが発生して正しい計算が行えていないことが確認できます。 ```cpp #include <iostream> #include <string> #include <vector> #include <algorithm> using namespace std; int main() { int a = 2000000000; int b = a * 2; cout << b << endl; int c = (a * 10 + 100) / 100; cout << c << endl; } ``` 実行結果 ``` -294967296 -14748363 ``` int型より広い範囲の整数を扱いたい場合、long long型という型を使うと良いです。long long型では、$-2^{63}$以上$2^{63}$未満、つまり-9,223,372,036,854,775,808以上9,223,372,036,854,775,807以下の整数を表すことができます。 絶対値が$2*10^{9}$より大きな数を扱いたい場合はlong long型を使うようにしましょう。 なお、long long型の変数を宣言するには次のようにします。 ```cpp #include <iostream> #include <string> #include <vector> #include <algorithm> using ll = long long; using namespace std; int main() { ll N; } ``` - キャスト c\++ではキャストと呼ばれる型の変換を行うことができ、例えばint型をlong long型に変換したりint型をdouble型に変換したりできます。 キャストの記法は以下のとおりです。 ``` (型)値 ``` 以下は数値型を変換する例です。 ```cpp #include <iostream> #include <string> #include <vector> #include <algorithm> using ll = long long; using namespace std; int main() { int a = 5; cout << (double)a << endl; // int型の値をdouble型に変換 double b = 3.141592; cout << (int)b << endl; // double型の値をint型に変換 } ``` 実行結果 ``` 5.00000 3 ``` - 文字列と数値の変換 - to_string関数 数値型から文字列に変換するには、to_string関数を用います。 ```cpp int number = 100; string s = to_string(number); cout << s + "yen" << endl; //100yen ``` - stoi, stoll関数 文字列型から数値型へ変換するには、stoi関数やstoll関数を用います。 ```cpp string s = "100"; int n = stoi(s); //stringからintへ変換 ll n2 = stoll(s); //stringからlong longへ変換 ``` ## ABCに出よう! 今まで学んだ内容でAtCoder Begginer ContestのA問題はほとんど解けるはずです。また、B問題、C問題についてもいくつかの問題は既に解けるはずです。 強くなりたい人は[AtCoder Problems](https://kenkoooo.com/atcoder/#/table/)を使ってどんどん問題を解きましょう!(まずはA, B問題を中心に解くことをおすすめします。安定してB問題が解けるようになったと感じたらC問題を解いていくと良いです) また、今後は是非毎週ABCに参加してください!コンテスト後には感想戦をやっているのでコンテストの成績にかかわらずこちらも是非参加してください!