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 C++14 (GCC 5.4.1) (judge verdict: Accepted)

#include <bits/stdc++.h>
#define REP(i, n) for (int i = 0; (i) < (int)(n); ++ (i))
#define REP3(i, m, n) for (int i = (m); (i) < (int)(n); ++ (i))
#define REP_R(i, n) for (int i = (int)(n) - 1; (i) >= 0; -- (i))
#define REP3R(i, m, n) for (int i = (int)(n) - 1; (i) >= (int)(m); -- (i))
#define ALL(x) begin(x), end(x)
#define dump(x) cerr << #x " = " << x << endl
using ll = long long;
using namespace std;
template <class T> using reversed_priority_queue = priority_queue<T, vector<T>, greater<T> >;
template <class T, class U> inline void chmax(T & a, U const & b) { a = max<T>(a, b); }
template <class T, class U> inline void chmin(T & a, U const & b) { a = min<T>(a, b); }
template <typename X, typename T> auto make_vectors(X x, T a) { return vector<T>(x, a); }
template <typename X, typename Y, typename Z, typename... Zs> auto make_vectors(X x, Y y, Z z, Zs... zs) { auto cont = make_vectors(y, z, zs...); return vector<decltype(cont)>(x, cont); }
template <typename T> ostream & operator << (ostream & out, vector<T> const & xs) { REP (i, (int)xs.size() - 1) out << xs[i] << ' '; if (not xs.empty()) out << xs.back(); return out; }

/**
 * @param m must be a positive integer
 * @note O(log y)
 */
ll modpow(ll x, ll y, int m) {
    assert (0 <= x and x < m);
    assert (0 <= y);
    ll z = 1;
    for (ll i = 1; i <= y; i <<= 1) {
        if (y & i) z = z * x % m;
        x = x * x % m;
    }
    return z;
}

/**
 * @param p must be a prime
 * @note O(log p)
 */
ll modinv(ll x, int p) {
    assert (x % p != 0);
    return modpow(x, p - 2, p);
}

/**
 * @brief Lagrange interpolation
 * @note O(n^2)
 */
vector<ll> lagrange_interpolate(const vector<pair<ll, ll> > & points, ll MOD) {
    // given ((x_0, y_1), \dots, (x_{n - 1}, y_{n - 1}))
    int n = points.size();

    // functions
    auto mul_monomial = [&](vector<ll> & f, ll a) {  // f \gets f \cdot (x - a)
        assert (f[n] == 0);
        REP_R (i, n + 1) {
            f[i] = ((i >= 1 ? f[i - 1] : 0) - a * f[i] % MOD + MOD) % MOD;
        }
    };
    auto div_monomial = [&](vector<ll> & f, ll a) {  // f \gets f / (x - a)
        ll last = 0;
        REP_R (i, n + 1) {
            swap(f[i], last);
            last = (last + a * f[i]) % MOD;
        }
    };
    auto apply = [&](vector<ll> & f, ll x) {  // f(x)
        ll y = 0;
        REP_R (i, n + 1) {
            y = (y * x + f[i]) % MOD;
        }
        return y;
    };

    // let g = \prod_i (x - x_i)
    // let g_i = g / (x - x_i)
    // assert for all j \ne i. g_i(x_j) = 0
    vector<ll> g(n + 1);
    g[0] = 1;
    for (auto point : points) {
        mul_monomial(g, point.first);
    }

    // let c_i = y_i / g_i(x_i)
    // let f = \sum_i c_i g_i / (x - x_i)
    // assert for all i. f(x_i) = y_i
    vector<ll> f(n + 1);
    for (auto point : points) {
        div_monomial(g, point.first);
        ll c_i = point.second * modinv(apply(g, point.first), MOD) % MOD;
        REP (j, n + 1) {
            f[j] = (f[j] + c_i * g[j]) % MOD;
        }
        mul_monomial(g, point.first);
    }
    assert (f.back() == 0);
    f.pop_back();
    return f;
}

vector<int> solve(int p, const vector<bool> & a) {
    vector<pair<ll, ll> > points;
    REP (i, p) {
        points.emplace_back(i, a[i]);
    }
    auto f = lagrange_interpolate(points, p);
    return vector<int>(ALL(f));
}

int main() {
    int p; cin >> p;
    vector<bool> a(p);
    REP (i, p) {
        int a_i; cin >> a_i;
        a[i] = a_i;
    }
    auto f = solve(p, a);
    REP (i, p) {
        cout << f[i] << ' ';
    }
    cout << endl;
    return 0;
}