Problem:
Score : 600 points

Problem Statement

Given are a prime number p and a sequence of p integers a_0, \ldots, a_{p-1} consisting of zeros and ones.

Find a polynomial of degree at most p-1, f(x) = b_{p-1} x^{p-1} + b_{p-2} x^{p-2} + \ldots + b_0, satisfying the following conditions:

For each i (0 \leq i \leq p-1), b_i is an integer such that 0 \leq b_i \leq p-1.

For each i (0 \leq i \leq p-1), f(i) \equiv a_i \pmod p.

Constraints

2 \leq p \leq 2999

p is a prime number.

0 \leq a_i \leq 1

Input

Input is given from Standard Input in the following format:

p
a_0 a_1 \ldots a_{p-1}

Output

Print b_0, b_1, \ldots, b_{p-1} of a polynomial f(x) satisfying the conditions, in this order, with spaces in between.

It can be proved that a solution always exists. If multiple solutions exist, any of them will be accepted.

Sample Input 1

2
1 0

Sample Output 1

1 1

f(x) = x + 1 satisfies the conditions, as follows:

f(0) = 0 + 1 = 1 \equiv 1 \pmod 2

f(1) = 1 + 1 = 2 \equiv 0 \pmod 2

Sample Input 2

3
0 0 0

Sample Output 2

0 0 0

f(x) = 0 is also valid.

Sample Input 3

5
0 1 0 1 0

Sample Output 3

0 2 0 1 3

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

#[allow(unused_imports)]
use std::cmp::*;
#[allow(unused_imports)]
use std::collections::*;
#[allow(unused_imports)]
use std::io::*;
#[allow(unused_imports)]
use std::iter;
#[allow(unused_imports)]
use std::mem::*;
#[allow(unused_imports)]
use std::str::*;
#[allow(unused_imports)]
use std::usize;

#[allow(unused_macros)]
macro_rules! read_cols {
    ($($t:ty),+) => {{
        let mut line = String::new();
        stdin().read_line(&mut line).unwrap();

        let mut it = line.trim()
            .split_whitespace();

        ($(
            it.next().unwrap().parse::<$t>().ok().unwrap()
        ),+)
    }}
}

#[allow(dead_code)]
fn read<T: FromStr>() -> T {
    let mut line = String::new();
    stdin().read_line(&mut line).unwrap();
    line.trim().to_string().parse().ok().unwrap()
}

#[allow(dead_code)]
fn read_vec<T: FromStr>() -> Vec<T> {
    let mut line = String::new();
    stdin().read_line(&mut line).unwrap();

    line.trim()
        .split_whitespace()
        .map(|s| s.parse().ok().unwrap())
        .collect()
}

fn combi(n: usize, p: usize) -> Vec<usize> {
    // C(n, r) = C(n - 1, r) + C(n - 1, r - 1)
    (0..n+1).fold(Vec::with_capacity(n + 1), |mut c, i| {
        c.push(1);
        for r in (1..i).rev() {
            c[r] = (c.get(r - 1).unwrap() + c.get(r).unwrap()) % p;
        }
        c[0] = 1;
        c
    })
}

fn main() {
    let p = read::<i64>();
    let a = read_vec::<i64>();

    let pu = p as usize;

    let c = combi(pu - 1, pu);

    let pow = (0..p).map(|x| {
        iter::once(1).chain((1..p).scan(1, |prev, _| {
            *prev = (*prev * x) % p;
            Some(*prev)
        })).collect::<Vec<_>>()
    }).collect::<Vec<_>>();

    // 1 - (x - i)^(p - 1)
    //  = 1 mod p when x = i
    //  = 0 mod p otherwise
    let coeffs = a.into_iter().enumerate().filter(|&(_, aa)| aa > 0).map(|(i, _)| i).fold(vec![0; pu], |mut coeffs, i| {
        let ii = i as i64;
        coeffs[0] = (coeffs.get(0).unwrap() + 1) % p;
        for j in 0usize..pu {
            let jj = j as i64;
            coeffs[j] = (coeffs.get(j).unwrap() + (if (p-jj) % 2 == 0 {1} else {-1}) * *c.get(j).unwrap() as i64 * pow[i][pu - 1 - j] + p) % p;
        }
        coeffs
    });

    println!("{}", coeffs.iter().map(|c| c.to_string()).collect::<Vec<String>>().join(" "));
}