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)

macro_rules ! input { ( source = $ s : expr , $ ( $ r : tt ) * ) => { let mut iter = $ s . split_whitespace ( ) ; input_inner ! { iter , $ ( $ r ) * } } ; ( iter = $ iter : ident , $ ( $ r : tt ) * ) => { let s = { use std :: io :: Read ; let mut s = String :: new ( ) ; std :: io :: stdin ( ) . read_to_string ( & mut s ) . unwrap ( ) ; s } ; let mut $ iter = s . split_whitespace ( ) ; input_inner ! { $ iter , $ ( $ r ) * } } ; ( $ ( $ r : tt ) * ) => { let s = { use std :: io :: Read ; let mut s = String :: new ( ) ; std :: io :: stdin ( ) . read_to_string ( & mut s ) . unwrap ( ) ; s } ; let mut iter = s . split_whitespace ( ) ; input_inner ! { iter , $ ( $ r ) * } } ; }
macro_rules ! input_inner { ( $ iter : expr ) => { } ; ( $ iter : expr , ) => { } ; ( $ iter : expr , mut $ var : ident : $ t : tt $ ( $ r : tt ) * ) => { let mut $ var = read_value ! ( $ iter , $ t ) ; input_inner ! { $ iter $ ( $ r ) * } } ; ( $ iter : expr , mut $ var : ident $ ( $ r : tt ) * ) => { input_inner ! { $ iter , mut $ var : usize $ ( $ r ) * } } ; ( $ iter : expr , $ var : ident : $ t : tt $ ( $ r : tt ) * ) => { let $ var = read_value ! ( $ iter , $ t ) ; input_inner ! { $ iter $ ( $ r ) * } } ; ( $ iter : expr , $ var : ident $ ( $ r : tt ) * ) => { input_inner ! { $ iter , $ var : usize $ ( $ r ) * } } ; }
macro_rules ! read_value { ( $ iter : expr , ( $ ( $ t : tt ) ,* ) ) => { ( $ ( read_value ! ( $ iter , $ t ) ) ,* ) } ; ( $ iter : expr , [ $ t : tt ; $ len : expr ] ) => { ( 0 ..$ len ) . map ( | _ | read_value ! ( $ iter , $ t ) ) . collect ::< Vec < _ >> ( ) } ; ( $ iter : expr , { chars : $ base : expr } ) => { read_value ! ( $ iter , String ) . chars ( ) . map ( | c | ( c as u8 - $ base as u8 ) as usize ) . collect ::< Vec < usize >> ( ) } ; ( $ iter : expr , { char : $ base : expr } ) => { read_value ! ( $ iter , { chars : $ base } ) [ 0 ] } ; ( $ iter : expr , chars ) => { read_value ! ( $ iter , String ) . chars ( ) . collect ::< Vec < char >> ( ) } ; ( $ iter : expr , char ) => { read_value ! ( $ iter , chars ) [ 0 ] } ; ( $ iter : expr , usize1 ) => { read_value ! ( $ iter , usize ) - 1 } ; ( $ iter : expr , $ t : ty ) => { $ iter . next ( ) . unwrap ( ) . parse ::<$ t > ( ) . unwrap ( ) } ; }
pub type Poly = Vec<i64>;
pub fn poly_add(x: &Poly, y: &Poly, p: i64) -> Poly {
    let (x, y) = if x.len() < y.len() { (y, x) } else { (x, y) };
    let mut x = x.clone();
    for j in 0..y.len() {
        x[j] = (x[j] + y[j]) % p;
    }
    x
}
pub fn poly_mul(x: &Poly, y: &Poly, p: i64) -> Poly {
    let mut res = vec![0; x.len() + y.len() - 1];
    for i in 0..x.len() {
        for j in 0..y.len() {
            res[i + j] = (res[i + j] + x[i] * y[j] % p) % p;
        }
    }
    res
}
pub fn poly_div(x: &Poly, y: &Poly, p: i64) -> Poly {
    let mut x = x.clone();
    let mut res = vec![];
    for i in (y.len() - 1..x.len()).rev() {
        let t = x[i] / y[y.len() - 1];
        res.push(t);
        for j in 0..y.len() {
            x[i - j] = ((x[i - j] - t * y[y.len() - 1 - j] % p) % p + p) % p;
        }
    }
    res.reverse();
    res
}
pub fn poly_mod(x: &Poly, y: &Poly, p: i64) -> Poly {
    let mut x = x.clone();
    for i in (y.len() - 1..x.len()).rev() {
        let t = x[i] / y[y.len() - 1];
        for j in 0..y.len() {
            x[i - j] = ((x[i - j] - t * y[y.len() - 1 - j] % p) % p + p) % p;
        }
    }
    x.truncate(y.len() - 1);
    x
}
pub fn poly_assign(x: &Poly, a: i64, p: i64) -> i64 {
    let mut res = 0;
    for &c in x.iter().rev() {
        res = (res * a % p + c) % p;
    }
    res
}
pub fn extgcd(a: i64, b: i64) -> (i64, i64, i64) {
    if b == 0 {
        (a, 1, 0)
    } else {
        let (g, x, y) = extgcd(b, a % b);
        (g, y, x - (a / b) * y)
    }
}
pub fn modinv(a: i64, p: i64) -> i64 {
    (extgcd(a, p).1 % p + p) % p
}
fn main() {
    input! { p, a: [i64; p] };
    let mut b = vec![1];
    let mut f = vec![0; p];
    let p = p as i64;
    for i in 0..p {
        b = poly_mul(&b, &vec![-i % p, 1], p);
    }
    for i in 0..p {
        if a[i as usize] == 1 {
            let m = poly_div(&b, &vec![-i % p, 1], p);
            let t = vec![modinv(poly_assign(&m, i, p), p)];
            f = poly_add(&f, &poly_mul(&m, &t, p), p);
        }
    }
    for i in 0..p as usize {
        print!("{} ", f[i]);
    }
    println!("");
}