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.42.0) (judge verdict: Accepted)

#![allow(dead_code,unused_variables)]
use proconio::{fastout, input};

fn pow(x : usize, k:usize) -> Modint{
    let mut tmp :Modint = 1.into();
    let mut m = k;
    let mut d : Modint = x.into();
    if k == 0{
        return 1.into();
    }
    while m > 0{
        if m&1 == 1{
            tmp *= d;
        }
        d *= d;
        m >>= 1;
    }
    tmp
}

#[fastout]
fn main() {
    input!{
        p: usize,
        a:[usize;p],
    }
    unsafe{MOD = p;}

    let mut b : Vec<Modint> = vec![0.into();p];
    let mut cnt : Modint = 0.into();
    let c = Combination::new(3000,p);
    for i in 0..p{
        if a[i] == 0{
            continue;
        }
        cnt += 1.into();
        for j in 0..p{
            let d = c.comb(p-1,j) * pow(i,p-1-j);
            if (p-1-j)%2 == 1{
                b[j] += d;
            }else{
                b[j] -= d;
            }
        }
    }
    b[0] += cnt;

    for i in 0..p{
        if i>0{
            print!(" ");
        }
        print!("{}",b[i]);
    }
    println!("");
}

use std::ops::*;
use std::mem::swap;
use std::fmt;

static mut MOD:usize = 0;

#[derive(Copy,Clone)]
pub struct Modint{
    val : usize,
}

impl Modint{
    pub fn new(val : usize) -> Self{
        Modint{
            val : unsafe{val%MOD},
        }
    }

    fn inv(&self) -> Self{
        let mut x : i32= 1;
        let mut u : i32= 0;
        let mut s : i32= self.val as i32;
        let mut t : i32= unsafe{MOD as i32};

        while t != 0{
            let k = s/t;
            s -= k * t;
            swap(&mut s,&mut t);
            x -= k * t;
            swap(&mut x, &mut u);
        }
        x %= unsafe{MOD as i32};
        if x < 0{
            x += unsafe{MOD as i32};
        }
        
        let x = x as usize;
        Modint{
            val : x,
        }
    }
}

impl Add for Modint{
    type Output = Self;

    fn add(self, rhs: Self) -> Self {
        Self {
            val : unsafe{(self.val + rhs.val) % MOD},
        }
    }
}

impl AddAssign for Modint {
    fn add_assign(&mut self, rhs: Modint) {
        *self = *self + rhs;
    }
}

impl Sub for Modint{
    type Output = Self;

    fn sub(self, other: Self) -> Self {
        Self {
            val :unsafe{(MOD + self.val - other.val) % MOD},
        }
    }
}

impl SubAssign for Modint {
    fn sub_assign(&mut self, rhs: Modint) {
        *self = *self - rhs;
    }
}

impl Mul for Modint {
    type Output = Modint;

    fn mul(self, rhs: Modint) -> Self {
        Modint{
            val : unsafe{(self.val * rhs.val) % MOD},
        }
    }
}

impl MulAssign for Modint {
    fn mul_assign(&mut self, rhs: Modint) {
        *self = *self * rhs;
    }
}

impl Div for Modint {
    type Output = Modint;

    fn div(self, rhs: Modint) -> Self {
        Modint{
            val : unsafe{(self.val * rhs.inv().val) % MOD},
        }
    }
}

impl DivAssign for Modint {
    fn div_assign(&mut self, rhs: Modint) {
        *self = *self / rhs;
    }
}

impl From<i32> for Modint{
    fn from(x : i32) -> Self {
        let mut tmp = x;
        while tmp < 0{
            tmp += unsafe{MOD as i32};
        }
        let res = Modint::new(tmp as usize);
        res
    }
}

impl From<usize> for Modint{
    fn from(x : usize) -> Self {
        let res = Modint::new(x);
        res
    }
}

impl fmt::Display for Modint{
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{}", self.val)
    }
}

pub struct Combination{
    fac : Vec<usize>,
    finv : Vec<usize>,
    m : usize,
}

impl Combination{
    pub fn new(n : usize, m : usize) -> Self{
        let mut inv = vec![1;n+1];
        let mut fac = vec![1;n+1];
        let mut finv = vec![1;n+1];

        for i in 2..(n+1){
            fac[i] = (fac[i-1] * i) % m;
            inv[i] = m - (inv[m%i] * (m/i) % m);
            finv[i] = (finv[i-1]*inv[i])%m;
        }

        Combination{
            fac,
            finv,
            m,
        }
    }

    pub fn comb(&self, n : usize, k: usize) -> Modint{
        if n < k{
            return 0.into();
        }

        Modint{val:(self.fac[n] * (self.finv[k] * self.finv[n-k] % self.m)) % self.m}
    }
}