Task: | Kortit II |
Sender: | EmuBird |
Submission time: | 2024-11-02 14:25:24 +0200 |
Language: | Rust (2021) |
Status: | READY |
Result: | 8 |
group | verdict | score |
---|---|---|
#1 | ACCEPTED | 3 |
#2 | ACCEPTED | 5 |
#3 | TIME LIMIT EXCEEDED | 0 |
#4 | TIME LIMIT EXCEEDED | 0 |
#5 | TIME LIMIT EXCEEDED | 0 |
test | verdict | time | group | |
---|---|---|---|---|
#1 | ACCEPTED | 0.00 s | 1, 2, 3, 4, 5 | details |
#2 | ACCEPTED | 0.02 s | 2, 3, 4, 5 | details |
#3 | TIME LIMIT EXCEEDED | -- | 3, 4, 5 | details |
#4 | TIME LIMIT EXCEEDED | -- | 4, 5 | details |
#5 | TIME LIMIT EXCEEDED | -- | 5 | details |
#6 | TIME LIMIT EXCEEDED | -- | 5 | details |
Compiler report
warning: unused variable: `a_plays_1` --> input/code.rs:66:60 | 66 | ...k = Callback { callback: |a_plays_1: &Vec<u32>, b_plays_1: Option<&Vec<u32>>, a_plays_2: Option<&Vec<u32>>, b_plays_2: Option<&Vec<u32... | ^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_a_plays_1` | = note: `#[warn(unused_variables)]` on by default warning: unused variable: `b_plays_1` --> input/code.rs:66:82 | 66 | ...k: |a_plays_1: &Vec<u32>, b_plays_1: Option<&Vec<u32>>, a_plays_2: Option<&Vec<u32>>, b_plays_2: Option<&Vec<u32>>, total_cards: u32, ... | ^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_b_plays_1` warning: unused variable: `a_plays_2` --> input/code.rs:66:112 | 66 | ...ays_1: Option<&Vec<u32>>, a_plays_2: Option<&Vec<u32>>, b_plays_2: Option<&Vec<u32>>, total_cards: u32, draws: u32, a_points: u32, b_p... | ^^^^^^^^^ help: if this is...
Code
use std::cell::RefCell; use std::collections::HashSet; use std::io; const MOD: u128 = 10u128.pow(9) + 7; fn main() { let stdin = io::stdin(); let t: u32 = { let mut input: String = String::new(); stdin.read_line(&mut input).unwrap(); input.trim().parse().unwrap() }; for _ in 0..t { let values: Vec<u32> = { let mut input: String = String::new(); stdin.read_line(&mut input).unwrap(); input.trim().split_whitespace().map(|x| x.parse::<u32>().unwrap()).collect() }; let answer = generate_answer(values[0], values[1], values[2]); println!("{}", answer); } } fn generate_answer(total_cards: u32, a_points: u32, b_points: u32) -> u128 { let total_points = a_points + b_points; if total_points > total_cards || total_points > 0 && (a_points >= total_points || b_points >= total_points) { return 0; } let draws = total_cards - a_points - b_points; let mut combinations: RefCell<u32> = RefCell::new(0); // Cards [(total_cards - draws + 1), total_cards] are consumed for draws. // no-op // A wins a_points times. // When A uses card (total_cards - draws), it must win. a_points - 1 are still left to be chosen. let mut a_plays = Vec::<u32>::from([total_cards - draws]); // This vec has its elements in descending order (largest first). // Permutations are not yet taken into account, so drawing cards from largest to smallest is fine. let mut a_callback = Callback { callback: |a_plays: &Vec<u32>, _: Option<&Vec<u32>>, _: Option<&Vec<u32>>, _: Option<&Vec<u32>>, total_cards: u32, draws: u32, a_points: u32, b_points: u32, counter: &mut RefCell<u32>| { let mut b_plays = Vec::<u32>::new(); // This vec has its elements in the same order as a_plays. let mut b_used_cards = HashSet::new(); let mut b_callback = Callback { callback: |a_plays_1: &Vec<u32>, b_plays_1: Option<&Vec<u32>>, _: Option<&Vec<u32>>, _: Option<&Vec<u32>>, total_cards: u32, draws: u32, a_points: u32, b_points: u32, counter: &mut RefCell<u32>| { let a_plays_2: Vec<u32> = { let mut a_plays_2_set: HashSet<u32> = (1..=(total_cards - draws)).collect(); for a in a_plays_1 { a_plays_2_set.remove(a); } a_plays_2_set.iter().map(|x| *x).collect() }; let mut b_plays_2 = Vec::<u32>::new(); let mut b_used_cards = HashSet::new(); // TODO: reuse the old set for b in b_plays_1.unwrap() { b_used_cards.insert(*b); } //println!("B lose callback: \n\tA plays 1: {:?}\n\tB plays 1: {:?}\n\tA plays 2: {:?}", a_plays_1, b_plays_1, a_plays_2); let mut b_win_callback = Callback { callback: |a_plays_1: &Vec<u32>, b_plays_1: Option<&Vec<u32>>, a_plays_2: Option<&Vec<u32>>, b_plays_2: Option<&Vec<u32>>, total_cards: u32, draws: u32, a_points: u32, b_points: u32, counter: &mut RefCell<u32>| { counter.replace_with(|x| -> u32 { *x + 1}); }, total_cards, draws, a_points, b_points, counter}; choose_b_win(&a_plays_1, &a_plays_2, &b_plays_1.unwrap(), &mut b_plays_2, &mut b_used_cards, total_cards, draws, a_points, b_points, &mut b_win_callback); }, total_cards, draws, a_points, b_points, counter}; choose_b_lose(&a_plays, &mut b_plays, &mut b_used_cards, total_cards, draws, a_points, b_points, &mut b_callback); }, total_cards, draws, a_points, b_points, counter: &mut combinations}; choose_a_win(a_points, &mut a_plays, &mut a_callback); let mut combinations: u128 = combinations.take() as u128; // The cards resulting in draws could be any card. combinations = (combinations % MOD) * (nCr(total_cards as u128, draws as u128) % MOD); let combinations_with_permutations = combinations * (factorial(total_cards as u128) % MOD); combinations_with_permutations % MOD } fn nCr(n: u128, k: u128) -> u128 { if k > n { 0 } else { factorial(n) / (factorial(k) * factorial(n - k)) } } fn factorial(n: u128) -> u128 { (1..=n).product::<u128>() } struct Callback<'a> { callback: fn(&Vec<u32>, Option<&Vec<u32>>, Option<&Vec<u32>>, Option<&Vec<u32>>, u32, u32, u32, u32, &mut RefCell<u32>), total_cards: u32, draws: u32, a_points: u32, b_points: u32, counter: &'a mut RefCell<u32> } impl Callback<'_> { fn invoke(&mut self, plays_a_1: &Vec<u32>, plays_b_1: Option<&Vec<u32>>, plays_a_2: Option<&Vec<u32>>, plays_b_2: Option<&Vec<u32>>) { (self.callback)(plays_a_1, plays_b_1, plays_a_2, plays_b_2, self.total_cards, self.draws, self.a_points, self.b_points, self.counter); } } fn choose_a_win(a_points: u32, a_plays: &mut Vec<u32>, callback: &mut Callback) { if a_plays.len() >= a_points as usize { callback.invoke(a_plays, None, None, None); return; } let max = a_plays.last().unwrap() - 1; let min = 1 + a_points - a_plays.len() as u32; // The card must be between [min, max]. for a_card in min..=max { a_plays.push(a_card); choose_a_win(a_points, a_plays, callback); a_plays.pop(); } } fn choose_b_lose(a_plays: &Vec<u32>, b_plays: &mut Vec<u32>, b_used_cards: &mut HashSet<u32>, total_cards: u32, draws: u32, a_points: u32, b_points: u32, callback: &mut Callback) { if b_plays.len() >= a_plays.len() { callback.invoke(a_plays, Some(b_plays), None, None); return; } let max = a_plays[b_plays.len()] - 1; let mut range = 1..=max; if b_plays.len() == a_plays.len() - 1 && !b_used_cards.contains(&1) { range = 1..=1; // If this is the last card and 1 hasn't been used yet, it must be used now. } for b_card in range { if b_used_cards.contains(&b_card) { continue; } b_used_cards.insert(b_card); b_plays.push(b_card); choose_b_lose(a_plays, b_plays, b_used_cards, total_cards, draws, a_points, b_points, callback); b_plays.pop(); b_used_cards.remove(&b_card); } } fn choose_b_win(a_plays_1: &Vec<u32>, a_plays_2: &Vec<u32>, b_plays_1: &Vec<u32>, b_plays_2: &mut Vec<u32>, b_used_cards: &mut HashSet<u32>, total_cards: u32, draws: u32, a_points: u32, b_points: u32, callback: &mut Callback) { if b_plays_2.len() >= b_points as usize { callback.invoke(a_plays_1, Some(b_plays_2), Some(a_plays_1), Some(b_plays_2)); return; } let max = total_cards - draws; let min = a_plays_2[b_plays_2.len()] + 1; let range = min..=max; for b_card in range { if b_used_cards.contains(&b_card) { continue; } b_used_cards.insert(b_card); b_plays_2.push(b_card); choose_b_win(a_plays_1 , a_plays_2, b_plays_1, b_plays_2, b_used_cards, total_cards, draws, a_points, b_points, callback); b_plays_2.pop(); b_used_cards.remove(&b_card); } }
Test details
Test 1
Group: 1, 2, 3, 4, 5
Verdict: ACCEPTED
input |
---|
54 4 4 0 3 1 3 3 2 2 4 0 4 ... |
correct output |
---|
0 0 0 0 0 ... |
user output |
---|
0 0 0 0 0 ... |
Test 2
Group: 2, 3, 4, 5
Verdict: ACCEPTED
input |
---|
284 6 1 0 5 0 2 7 1 5 7 7 5 ... |
correct output |
---|
0 0 35280 0 36720 ... |
user output |
---|
0 0 35280 0 36720 ... |
Test 3
Group: 3, 4, 5
Verdict: TIME LIMIT EXCEEDED
input |
---|
841 19 3 12 19 19 13 19 7 13 20 11 15 ... |
correct output |
---|
40291066 0 0 0 0 ... |
user output |
---|
(empty) |
Test 4
Group: 4, 5
Verdict: TIME LIMIT EXCEEDED
input |
---|
1000 15 12 6 7 1 6 44 4 26 6 6 5 ... |
correct output |
---|
0 5040 494558320 0 340694548 ... |
user output |
---|
(empty) |
Test 5
Group: 5
Verdict: TIME LIMIT EXCEEDED
input |
---|
1000 892 638 599 966 429 655 1353 576 1140 1403 381 910 ... |
correct output |
---|
0 0 0 249098285 0 ... |
user output |
---|
(empty) |
Test 6
Group: 5
Verdict: TIME LIMIT EXCEEDED
input |
---|
1000 2000 1107 508 2000 1372 249 2000 588 65 2000 1739 78 ... |
correct output |
---|
750840601 678722180 744501884 159164549 868115056 ... |
user output |
---|
(empty) |