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, m: usize) -> i64{
    let mut res = 1;
    let mut n = k;
    let mut a = x;
    while n > 0{
        if n&1 == 1{
            res = (res * a)%m;
        }
        a = (a * a)% m;
        n >>= 1;
    }
    res as i64
}

fn main() {
    input!{
        p: usize,
        a:[i64;p],
    }

    let mut b : Vec<i64> = vec![0;p as usize];
    let pp = p as i64;
    let c = Combination::new(p+10,p);
    for i in 0..p{
        b[0] = (b[0] + a[i])%pp;
        if i==0{
            if a[i] == 1{
                b[p-1] -= 1;
            }
            if b[p-1] < 0{
                b[p-1] += pp;
            }
        }else{
            if a[i] == 0{
                continue;
            }
            for j in 0..p{
                let d = c.comb(p-1,j) * pow(i,p-1-j,p);
                // println!("{} comb : {} pow ; {}",d,c.comb(p-1,j),pow(i,p-1-j,p));
                if (p-1-j)%2 == 1{
                    b[j] += d;
                }else{
                    b[j] -= d;
                }
                b[j] %= pp;
                if b[j] < 0{
                    b[j] += pp;
                }
            }
        }     
    }


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

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) -> i64{
        if n < k{
            return 0;
        }

        ((self.fac[n] * (self.finv[k] * self.finv[n-k] % self.m)) % self.m)as i64
    }
}