2023-01-12 ABC057 の A, B, C, D を解いた / Iterator::position の複数回呼び出し
ABC057 : AtCoder Beginner Contest 057 の A, B, C, D を解いた。
- A - Remaining Time
https://atcoder.jp/contests/abc057/tasks/abc057_a
- 提出: https://atcoder.jp/contests/abc057/submissions/37963192
(a + b) % 24
- B - Checkpoints
https://atcoder.jp/contests/abc057/tasks/abc057_b
- 提出: https://atcoder.jp/contests/abc057/submissions/37963285
- N, M が小さいので各学生について最も近いチェックポイントを調べれば良い
- C - Digits in Multiplication
https://atcoder.jp/contests/abc057/tasks/abc057_c
- 提出: https://atcoder.jp/contests/abc057/submissions/37963391
A * B
を動くと書いてあるので約数を列挙して走査すれば良い- 約数の列挙は
O(√N)
なのでN<=10^10
でも間に合う
- D - Maximum Average Sets
https://atcoder.jp/contests/abc057/tasks/abc057_d
- 提出: https://atcoder.jp/contests/abc057/submissions/37964143
- 最大の平均値は降順に並べて先頭から A 個とった和を A 個で割れば良い
- 個数が増えたとき平均値は下がることはあっても上がることはないので A 個で良い
- 場合の数は平均値を下げずに選び方を変えられるかを考える
- 降順に並べて先頭から A 個目の数字と先頭の数字が同じなら、選択する数を増やしても A 個目と同じ数字を選ぶ限りは平均値は下がらない
- 降順に並べて先頭から A 個目の数字と先頭の数字が同じでないときも、選択する数を増やさず、 A 個目と同じ数字を選び変える限りは平均値は下がらない
- あとは選べる個数から選ぶ個数を nCk で求める
use proconio::input;
fn choose(n: usize, r: usize) -> usize {
if n < r {
return 0;
}
if r == 0 {
return 1;
}
let mut m = 1;
for i in 0..r {
m *= n - i;
m /= i + 1;
}
m
}
fn main() {
input! {
n: usize,
a: usize,
b: usize,
mut v: [usize; n],
};
v.sort();
v.reverse();
let avg = v.iter().take(a).sum::<usize>() as f64 / a as f64;
let mut count_eqmin = 0_usize;
let mut count_fixed = 0_usize;
for (i, v_i) in v.iter().copied().enumerate() {
if v_i == v[a - 1] {
count_eqmin += 1;
if i < a {
count_fixed += 1;
}
}
}
let count = if v[0] == v[a - 1] {
(a..=b).map(|x| choose(count_eqmin, x)).sum::<usize>()
} else {
choose(count_eqmin, count_fixed)
};
println!("{}", avg);
println!("{}", count);
}
Iterator::position は &mut self
で iter を進める。複数回呼び出すと前回の最後に見つかった位置の次の位置から探索できることを知った。
fn main() {
let v = vec![1, 1, 1];
let mut iter = v.iter();
assert_eq!(iter.position(|x| x == &1), Some(0)); // next が v[0] を指す iter から探して 0 の位置
assert_eq!(iter.position(|x| x == &1), Some(0)); // next が v[1] を指す iter から探して 0 の位置
assert_eq!(iter.position(|x| x == &1), Some(0)); // next が v[2] を指す iter から探して 0 の位置
assert_eq!(iter.position(|x| x == &1), None);
}
今日のコミット。