Problem:
Score : 900 points

Problem Statement

You are given a sequence of N integers: A_1,A_2,...,A_N.

Find the number of permutations p_1,p_2,...,p_N of 1,2,...,N that can be changed to A_1,A_2,...,A_N by performing the following operation some number of times (possibly zero), modulo 998244353:

For each 1\leq i\leq N, let q_i=min(p_{i-1},p_{i}), where p_0=p_N. Replace the sequence p with the sequence q.

Constraints

1 \leq N \leq 3 × 10^5

1 \leq A_i \leq N

All values in input are integers.

Input

Input is given from Standard Input in the following format:

N
A_1
:
A_N

Output

Print the number of the sequences that satisfy the condition, modulo 998244353.

Sample Input 1

3
1
2
1

Sample Output 1

2

(2,3,1) and (3,2,1) satisfy the condition.

Sample Input 2

5
3
1
4
1
5

Sample Output 2

0

Sample Input 3

8
4
4
4
1
1
1
2
2

Sample Output 3

24

Sample Input 4

6
1
1
6
2
2
2

Sample Output 4

0

Solution in Rust (1.15.1) (judge verdict: Accepted)

macro_rules! input {
    (source = $s:expr, $($r:tt)*) => {
        let mut iter = $s.split_whitespace();
        let mut next = || { iter.next().unwrap() };
        input_inner!{next, $($r)*}
    };
    ($($r:tt)*) => {
        let stdin = std::io::stdin();
        let mut bytes = std::io::Read::bytes(std::io::BufReader::new(stdin.lock()));
        let mut next = move || -> String {
            bytes
                .by_ref()
                .map(|r| r.unwrap() as char)
                .skip_while(|c| c.is_whitespace())
                .take_while(|c| !c.is_whitespace())
                .collect()
        };
        input_inner!{next, $($r)*}
    };
}

macro_rules! input_inner {
    ($next:expr) => {};
    ($next:expr, ) => {};

    ($next:expr, $var:ident : $t:tt $($r:tt)*) => {
        let $var = read_value!($next, $t);
        input_inner!{$next $($r)*}
    };
}

macro_rules! read_value {
    ($next:expr, ( $($t:tt),* )) => {
        ( $(read_value!($next, $t)),* )
    };

    ($next:expr, [ $t:tt ; $len:expr ]) => {
        (0..$len).map(|_| read_value!($next, $t)).collect::<Vec<_>>()
    };

    ($next:expr, chars) => {
        read_value!($next, String).chars().collect::<Vec<char>>()
    };

    ($next:expr, usize1) => {
        read_value!($next, usize) - 1
    };

    ($next:expr, $t:ty) => {
        $next().parse::<$t>().expect("Parse error")
    };
}

use std::collections::BTreeMap;

fn main() {
    input!{
        n: usize,
        v: [usize; n]
    }
    let d = 998244353;

    let mut w = v;
    if w[0] == w[n - 1] {
        let mut i = 1;
        while i < n && w[0] == w[i] {
            i += 1;
        }
        if i < n {
            let mut l = w[0..i].into_iter().map(|x| *x).collect();
            w = w[i..n].into_iter().map(|x| *x).collect();
            w.append(&mut l);
        }
    }

    let mut counts: BTreeMap<usize, (usize, usize)> = BTreeMap::new();
    let mut counts_vec: Vec<(usize, usize)> = Vec::new();
    let mut c = 0;
    let mut num = w[0];
    for i in 0..w.len() {
        let x = w[i];
        if x == num {
            c += 1;
        } else {
            if counts.insert(num, (c, counts_vec.len() + 1)) != None {
                println!("0");
                return;
            }
            counts_vec.push((num,c));
            c = 1;
            num = x;
        }
    }
    if counts.insert(num, (c, counts_vec.len() + 1)) != None {
        println!("0");
        return;
    }
    counts_vec.push((num,c));
    counts_vec.insert(0, (num,c));
    let t = counts_vec[1];
    counts_vec.push(t);

    if w.iter().all(|x| *x == 1) {
        println!("{}", (1..n+1).fold(1, |ac, x| ac * x % d));
        return;
    }

    let len;
    if let Some(c) = counts.get(&1) {
        len = c.0;
    } else {
        println!("0");
        return;
    }

    let mut ans = 1;
    let mut lsum = 0;
    let mut p = 0;
    for m in 1..n+1 {
        if let Some(x) = counts.get(&m) {
            let (c, i) = *x;
            if c > len {
                println!("0");
                return;
            }
            if m > counts_vec[i - 1].0 && m > counts_vec[i + 1].0 {
                ans = ans * (len - c + 1) % d;
                p -= 1;
            } else if m < counts_vec[i - 1].0 && m < counts_vec[i + 1].0 {
                if c != len {
                    println!("0");
                    return;
                }
                p += 1;
            }
            lsum += c;
        } else {
            let mul = lsum + 1 - (len - 1) * p - m;
            ans = ans * mul % d;
            if mul == 0 {
                break;
            }
        }
    }
    println!("{}", ans);
}