1184->1214(Blue)
SRM 597 (div2), ox-, +50/-0, 264.1pts, 174th
Easy
for all elem = a {
amin = minelem(a), there exists m in N elem / amin = 2^m
}
を判定する。
どうでもいいけど、given nに対して、there exists m in N n=2^mの判定方法として、(n & n – 1)がある。
Med
result -1はソートして同一かチェック。
result m ⇔ B[m:end]がAの部分列
これだけで良いのだが、下の部分列として存在の実装をミスった。馬鹿です。部分問題に加えます。
ミスった原因。
-forやwhileがこんがらがる問題は、きちんと紙で構造を確かめなければならない。
-終端条件から考えると楽
-条件が網羅的であることを確認しなければならない
-終端条件が更新条件によって変わる場合がある。下の解法2参照。
-whileとbreak, continueの構造は極めてミスりやすいので、他の関数を作ったほうが良いと思われる。インクリメントの変数の取り扱いが面倒。
部分問題、string A, Bについて、AがBを部分列として持つかを判定せよ。
解法0:
B[i]がA[j:end]に存在するかを逐一チェック。
終端条件
i: last && A[j:end]にB[i]がある→true
i: last && A[j:end]にB[i]がない→false
i: not last && A[j:end]にB[i]がない→false
更新条件
i: not last && A[j:end]にB[i]がある→jをfind(A[j:end], B[i]) + 1に設定
解法1:
B[i]がA[j:end]に存在するかを逐一チェック。
終端条件
j: done →false
更新条件
j: not done && A[j] == B[i]→j++, break
j: not done && A[j] != B[i]→j++
解法2:
whileとforの混成は面倒なので、while(1)でi, jを自分で管理する。
終端条件
i: not done && j: done→false
i: done && j: not done→true
i: done && j: done→???
更新条件
i: not done && j: not done && A[j] == B[i]→i++, j++
i: not done && j: not done && A[j] != B[i]→j++
???は、更新条件1行目によって更新された時にのみ発生。これは???=doneとして扱うべき。
bool ans0(string A, string B)
{
int j = 0;
for (int i = 0; i < B.length(); i++, j++) {
int tmpj = A.substr(j, A.length() - j).find(B[i]);
if (tmpj == string::npos) {
return false;
} else if (i != B.length() - 1) {
j += tmpj;
} else {
return true;
}
}
return true;
}
bool ans1(string A, string B)
{
int j = 0;
for (int i = 0; i < B.length(); i++) {
while (1) {
if (A[j++] == B[i])
break;
if (j >= A.length())
return false;
}
}
return true;
}
bool ans2(string A, string B)
{
int i = 0, j = 0;
while (1) {
if (i >= B.length())
return true;
else if (j >= A.length())
return false;
else if (A[j] != B[i])
j++;
else {
i++, j++;
}
}
}
Hard
わけがわからないよ。
勉強します。