tqk's diary

競プロとか

ABC103 - tqkoh's diary

自分(参加時茶色コーダー())の解いた方法を載せます。

A問題

A - Task Scheduling Problem
3つの整数を並べ、間の差の和を最小化する問題。意味が分かりにくい。

解法

3つの整数a, b, cを小さい順に並べたとき、d,e,fとなるとすると、答えは
(e-d)+(f-e)=f-d =max(a,b,c)-min(a,b,c)

int a,b,c; cin>>a>>b>>c;
cout << max({ a, b, c }) - min({ a, b, c });

B問題

B - String Rotation
ある文字列Sの一番後ろの文字を一番前に持っていく、という操作を繰り返して文字列Tにできるか判定する問題。

解法

これは、Sを2つつなげた文字列の中にTが含まれているかを検索するだけで判定できる。 (愚直に書いても通った。)

string s, t; cin >> s >> t; s += s;
cout << (s.find(t) != string::npos ? "Yes\n" : "No\n");

C問題

C - Modulo Summation
a_1,a_2,...,a_nが与えられるので、f(x)=(m\ mod\ a_1)+(m\ mod\ a_2)+...+(m\ mod\ a_n) の最大値を求めるという問題。

解法

n=3, a_1=3,a_2=4,a_3=6 のとき、括弧ごとに分けて考えると、
f:id:tako0608:20180723010231p:plain:w300
このように、いつかはどこかで全て0になるところ(例ではf(lcm(3,4,6))=f(12))があるので、そのひとつ前(例ではf(11))が最大値になる。よって答えは
(a_1-1)+(a_2-1)+...+(a_n-1) =(a_1+a_2+...+a_n)-n

int n, in, sum = 0; cin >> n;
rep(i, n) {
    cin >> in; sum += in;
}
cout << sum - n;

D問題

D - Islands War
n個の島が横1列に並んでいて、間にn-1本の橋があり、「a_i 番目とb_i 番目の島が行き来できないようにする」という要望をすべて叶えるために切らなければならない橋の最小値を求める問題。

解法

(ひどい解法です。)
a_i 番目とb_i 番目の島が行き来できないようにする、という要望をa_i からb_i までの線分で表すと、たとえば次のようになる。
f:id:tako0608:20180723022524p:plain
これをすべて切る縦線が求まればいいのだが、この状態だとどこを切ればいいかわからないので、((a_i,b_i)a_iについてソートしてあるものを)a_iが同じもののうちでb_iについて降順でソートする。
f:id:tako0608:20180723020246p:plain
こうすることで、上から見ていき、右端が(次の要望の左端)以下の要望(次の図で赤い要望)さえ切ればそれより上はすべて切れることになる。
f:id:tako0608:20180723020822p:plain
よって、(1)左端昇順でソート(2)それごとに右端降順でソート(3)右端が(次の要望の左端)以下の要望の数を数え、それ+1(最後)が答えとなる。
(クソコードは以下にありますが見ないでください。本番中にきれいなコードが書けたことはありません)

Submission #2886100 - AtCoder Beginner Contest 103

学んだことメモ

  • sort()の仕組みが少しわかった。第三引数にどうやってソートするかを示した関数を渡すことで、pairのfirstを比較して並び替える、などができる。(比較関数、という。。。?)例: pair<int, int>の、secondを降順に並べるそれ
bool secgreater(const pair<int, int>& a, const pair<int, int>& b) return a.second > b.second;
  • つかうときは以下のようにする
sort(a, a+n, secgreater);
  • 標準の、intとかの降順ソートの比較関数?は()をつけるようだ
sort(b, b+n, greater<int>());

リンク

他にもこんな記事を書いています

qiita.com

tqk.hatenablog.jp