AtCoder AGC 035 C - Skolem XOR Tree (Rust)
irisruneです。Rust第一回ですが、余りにも茨の道すぎて早くも最終回が近い予感がしています。
前置き
Rustは入力がかなり難解なので下記サイトよりマクロを拝借しております。中身はほとんど理解できていません。本ブログ上では記述を省略します。
問題
本ブログ初の700点問題です。ある程度手計算で試すと最近の500点くらいに感じられました。
fn main() { input!{ n: usize } let mut m = 1; while m <= n { if m == n { println!("No"); return; } m *= 2; } println!("Yes"); m = 2; while m < n { println!("{} {}", 1, m); println!("{} {}", 1, m + 1); println!("{} {}", m, m + n + 1); println!("{} {}", m + 1, m + n); m += 2; } println!("{} {}", n + 1, n + 3); if n % 2 == 0 { m = n; let mut e = 0; while m > 1 { m /= 2; e += 1; } println!("{} {}", n, 2usize.pow(e)); println!("{} {}", n * 2, n + 1 - 2usize.pow(e)); } }
図がないと説明が難しいので、以下では公式解説を見ていることを前提とします。まず、が2のべき数(2のべき乗で表される数)の場合は条件を満たす木は存在しません。なぜなら、重みがより小さい数同士の排他的論理和は必ずより小さくなるためです。
次に、が3以上の奇数の場合について考えます。まず、の場合は入出力例1のように条件を満たす木を構成することができます。ここで頂点の重みについてのみ考えると公式解説の図(の一部)になります。
更にに増やした場合について考えると、木に対し重みが4,5の頂点を2つずつ追加することとなります。ここで端点でない重み1の頂点に対し、公式解説の図のように頂点を接続することで条件を満たす木を構成することができます。これは、整数に対してとなることから証明できます。
あとは同様の操作により、に対しても条件を満たす木を構成することができます。
最後にが(2のべき数でない)偶数の場合についてですが、重み1の頂点と重みの頂点が隣接していることと、(が2のべき数でないとき)となる2整数を用いてとなることから条件を満たす木を構成することができます。具体的な手順としては、より小さい最大の2のべき数をとおき、重み1の頂点に接続している重みの頂点それぞれに重みの頂点を接続すればよいです。
雑記
- グラフ(木)問題を解説する場合は図が必要となることが多いので鬼門ですね。
- グラフ作成ツールを探してくるべきだとは思います。
- A問題は一応正攻法で解きましたが時間もWAもかさんで大変でした。
嘘解法がなければC問題の方が簡単だと思います。