60 lines
1.8 KiB
Rust
60 lines
1.8 KiB
Rust
use std::collections::HashMap;
|
|
|
|
use proconio::input;
|
|
|
|
const MAX_RESULT: u64 = 1000000007;
|
|
|
|
fn calc_orders(ans: &[u64]) -> u64 {
|
|
let mut visited_positions: HashMap<u64, usize> = HashMap::new();
|
|
let mut result = 1;
|
|
let l = ans.len();
|
|
|
|
// For all reports, it needs to be at least 0 and at most n - 1.
|
|
if l % 2 == 0 {
|
|
for &a in ans.into_iter() {
|
|
// In this case, all reports have to be odd and occur twice.
|
|
// We don't have to check if a < 0 because a is unsigned and rust will panic during the
|
|
// parsing of the input anyways.
|
|
if a % 2 != 1 || a >= l as u64 {
|
|
return 0;
|
|
}
|
|
|
|
let number_of_reports = *visited_positions.get(&a).unwrap_or(&0);
|
|
if number_of_reports > 1 {
|
|
return 0;
|
|
} else if number_of_reports == 0 {
|
|
result = (result * 2) % MAX_RESULT;
|
|
}
|
|
visited_positions.insert(a, number_of_reports + 1);
|
|
}
|
|
} else if l % 2 == 1 {
|
|
// In this case, all reports have to be even, occur twice, except 0, which needs to occur
|
|
// exactly once.
|
|
for &a in ans.into_iter() {
|
|
if a % 2 != 0 || a >= l as u64 {
|
|
return 0;
|
|
}
|
|
|
|
let number_of_reports = *visited_positions.get(&a).unwrap_or(&0);
|
|
if number_of_reports > 1 || (number_of_reports > 0 && a == 0) {
|
|
return 0;
|
|
} else if a != 0 && number_of_reports == 0 {
|
|
result = (result * 2) % MAX_RESULT;
|
|
}
|
|
|
|
visited_positions.insert(a, number_of_reports + 1);
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
fn main() {
|
|
input! {
|
|
n: usize,
|
|
ans: [u64; n],
|
|
};
|
|
|
|
println!("{}", calc_orders(&ans));
|
|
}
|