#pragma GCC optimize("Ofast")
#include <bits/stdc++.h>
#define whlie while
#define pb push_back
#define eb emplace_back
#define fi first
#define se second
#define rep(i, N) for (int i = 0; i < (N); i++)
#define repr(i, N) for (auto i = (N)-1; i >= 0; i -= 1)
#define each(x, v) for (auto &x : v)
#define all(v) (v).begin(), (v).end()
#define sz(v) ((int)(v).size())
#define vrep(v, it) for (auto it = v.begin(); it != v.end(); it++)
#define vrepr(v, it) for (auto it = v.rbegin(); it != v.rend(); it++)
#define ini(...)   \
  int __VA_ARGS__; \
  in(__VA_ARGS__)
#define inl(...)  \
  ll __VA_ARGS__; \
  in(__VA_ARGS__)
#define ins(...)      \
  string __VA_ARGS__; \
  in(__VA_ARGS__)
#define rand mtrand
using namespace std;
using ll = long long;
using vi = vector<int>;
using vl = vector<ll>;
using vvi = vector<vector<int>>;
constexpr int inf = 1001001001;
constexpr ll infLL = 0x1FFFFFFFFFFFFFFFLL;
struct IoSetupNya {
  IoSetupNya() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    cout << fixed << setprecision(15);
    cerr << fixed << setprecision(15);
  }
} iosetupnya;
template <typename T, typename U>
inline bool amin(T &x, U y) {
  return (y < x) ? (x = y, true) : false;
}
template <typename T, typename U>
inline bool amax(T &x, U y) {
  return (x < y) ? (x = y, true) : false;
}
template <typename T, typename U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
  os << p.first << " " << p.second;
  return os;
}
template <typename T, typename U>
istream &operator>>(istream &is, pair<T, U> &p) {
  is >> p.first >> p.second;
  return is;
}
template <typename T>
ostream &operator<<(ostream &os, const vector<T> &v) {
  int s = (int)v.size();
  rep(i, s) os << (i ? " " : "") << v[i];
  return os;
}
template <typename T>
istream &operator>>(istream &is, vector<T> &v) {
  for (auto &x : v) is >> x;
  return is;
}
void in() {}
template <typename T, class... U>
void in(T &t, U &... u) {
  cin >> t;
  in(u...);
}
void out() { cout << "\n"; }
template <typename T, class... U>
void out(const T &t, const U &... u) {
  cout << t;
  if (sizeof...(u)) cout << " ";
  out(u...);
}
template <typename T>
void die(T x) {
  out(x);
  exit(0);
}

#define trc(...)                   \
  do {                             \
    cerr << #__VA_ARGS__ << " = "; \
    dbg_out(__VA_ARGS__);          \
  } while (0)
#define trca(v, N)       \
  do {                   \
    cerr << #v << " = "; \
    array_out(v, N);     \
  } while (0)
#define trcc(v)                             \
  do {                                      \
    cerr << #v << " = {";                   \
    each(x, v) { cerr << " " << x << ","; } \
    cerr << "}" << endl;                    \
  } while (0)
template <typename T>
void _cout(const T &c) {
  cerr << c;
}
void _cout(const int &c) {
  if (c == 1001001001)
    cerr << "inf";
  else if (c == -1001001001)
    cerr << "-inf";
  else
    cerr << c;
}
void _cout(const unsigned int &c) {
  if (c == 1001001001)
    cerr << "inf";
  else
    cerr << c;
}
void _cout(const long long &c) {
  if (c == 1001001001 || c == (1LL << 61) - 1)
    cerr << "inf";
  else if (c == -1001001001 || c == -((1LL << 61) - 1))
    cerr << "-inf";
  else
    cerr << c;
}
void _cout(const unsigned long long &c) {
  if (c == 1001001001 || c == (1LL << 61) - 1)
    cerr << "inf";
  else
    cerr << c;
}
template <typename T, typename U>
void _cout(const pair<T, U> &p) {
  cerr << "{ ";
  _cout(p.fi);
  cerr << ", ";
  _cout(p.se);
  cerr << " } ";
}
template <typename T>
void _cout(const vector<T> &v) {
  int s = v.size();
  cerr << "{ ";
  for (int i = 0; i < s; i++) {
    cerr << (i ? ", " : "");
    _cout(v[i]);
  }
  cerr << " } ";
}
template <typename T>
void _cout(const vector<vector<T>> &v) {
  cerr << "[ ";
  for (const auto &x : v) {
    cerr << endl;
    _cout(x);
    cerr << ", ";
  }
  cerr << endl << " ] ";
}
void dbg_out() { cerr << endl; }
template <typename T, class... U>
void dbg_out(const T &t, const U &... u) {
  _cout(t);
  if (sizeof...(u)) cerr << ", ";
  dbg_out(u...);
}
template <typename T>
void array_out(const T &v, int s) {
  cerr << "{ ";
  for (int i = 0; i < s; i++) {
    cerr << (i ? ", " : "");
    _cout(v[i]);
  }
  cerr << " } " << endl;
}
template <typename T>
void array_out(const T &v, int H, int W) {
  cerr << "[ ";
  for (int i = 0; i < H; i++) {
    cerr << (i ? ", " : "");
    array_out(v[i], W);
  }
  cerr << " ] " << endl;
}
using P = pair<int, int>;
random_device seed_gen;
mt19937_64 mtrand(seed_gen());
//////////////////////////////////////////

template <int mod, int primitiveroot>
struct NumberTheoreticTransform {
  vector<vector<int>> rts, rrts;
  void ensure_base(int N) {
    if ((int)rts.size() >= N) return;
    rts.resize(N), rrts.resize(N);
    for (int i = 1; i < N; i <<= 1) {
      if (rts[i].size()) continue;
      int w = mod_pow(primitiveroot, (mod - 1) / (i * 2));
      int rw = inverse(w);
      rts[i].resize(i), rrts[i].resize(i);
      rts[i][0] = 1, rrts[i][0] = 1;
      for (int k = 1; k < i; k++) {
        rts[i][k] = mul(rts[i][k - 1], w);
        rrts[i][k] = mul(rrts[i][k - 1], rw);
      }
    }
  }

  inline int mod_pow(int x, int n) {
    int ret = 1;
    while (n > 0) {
      if (n & 1) ret = mul(ret, x);
      x = mul(x, x);
      n >>= 1;
    }
    return ret;
  }

  inline int inverse(int x) { return mod_pow(x, mod - 2); }

  inline int add(int x, int y) {
    x += y;
    if (x >= mod) x -= mod;
    return x;
  }

  inline int mul(int a, int b) { return int(1LL * a * b % mod); }

  void DiscreteFourierTransform(vector<int> &F, bool rev) {
    const int N = (int)F.size();
    ensure_base(N);
    for (int i = 0, j = 1; j + 1 < N; j++) {
      for (int k = N >> 1; k > (i ^= k); k >>= 1)
        ;
      if (i > j) swap(F[i], F[j]);
    }
    for (int i = 1; i < N; i <<= 1) {
      for (int j = 0; j < N; j += i * 2) {
        for (int k = 0; k < i; k++) {
          int s = F[j + k], t = mul(F[j + k + i], rev ? rrts[i][k] : rts[i][k]);
          F[j + k] = add(s, t), F[j + k + i] = add(s, mod - t);
        }
      }
    }
    if (rev) {
      int temp = inverse(N);
      for (int i = 0; i < N; i++) F[i] = mul(F[i], temp);
    }
  }

  vector<int> Multiply(const vector<int> &A, const vector<int> &B) {
    int sz = 1;
    while (sz < int(A.size()) + int(B.size()) - 1) sz <<= 1;
    vector<int> F(sz), G(sz);
    for (int i = 0; i < (int)A.size(); i++) F[i] = A[i];
    for (int i = 0; i < (int)B.size(); i++) G[i] = B[i];
    DiscreteFourierTransform(F, false);
    DiscreteFourierTransform(G, false);
    for (int i = 0; i < sz; i++) F[i] = mul(F[i], G[i]);
    DiscreteFourierTransform(F, true);
    F.resize(A.size() + B.size() - 1);
    return F;
  }
};
NumberTheoreticTransform<1012924417, 5> ntt_conv;

// 任意長NTT
// b[i] = Σ a[j] r^(ij) (mod p) (0 <= i,j <= p-2)を計算する
template <typename T>
struct ArbitaryLengthNTT {
  T prime, size_;  // 要素数 n = p - 1
  vector<T> pr;
  ArbitaryLengthNTT(T pp) : prime(pp) {
    // rのべき乗
    T p_primitive = primitive(prime);
    pr.resize(prime);
    pr[0] = 1;
    for (int i = 1; i < prime; i++) pr[i] = pr[i - 1] * p_primitive % prime;
  }

  vector<T> mul(vector<T> &a) {
    size_ = T(a.size());
    assert(size_ + 1 == prime);
    if (size_ == 1) return vector<T>({a[0]});
    vector<T> ret;
    CooleyTukey(a, ret);
    return ret;
  }

  void CooleyTukey(vector<T> &f, vector<T> &ret) {
    T N = f.size();
    assert(size_ % N == 0);
    T P = iscomposite(N);
    if (P == 0) {
      Rader(f, ret);
      return;
    }
    T Q = N / P;
    vector<T> f1(N);
    {
      vector<T> f2(Q), f3(Q);
      for (int p = 0; p < P; p++) {
        for (int q = 0; q < Q; q++) f2[q] = f[q * P + p];
        CooleyTukey(f2, f3);
        for (int r = 0; r < Q; r++) {
          f1[p * Q + r] = pr[size_ / N * r % size_ * p % size_] * f3[r] % prime;
        }
      }
    }
    ret.resize(N);
    {
      vector<T> f(P), fret(P);
      for (int r = 0; r < Q; r++) {
        for (int p = 0; p < P; p++) f[p] = f1[p * Q + r];
        Rader(f, fret);
        for (int s = 0; s < P; s++) ret[s * Q + r] = fret[s] % prime;
      }
    }
  }

  void Rader(vector<T> &f, vector<T> &ret) {
    T P = f.size();
    assert(size_ % P == 0);
    T g = primitive(P);
    T ginv = modpow(g, P - 2, P);
    vector<T> f2(P - 1), f3(P - 1);
    for (T x = 0, cur = 1, curinv = 1; x < P - 1; x++) {
      f2[x] = f[cur];
      f3[x] = pr[size_ / P * curinv % size_];
      cur = cur * g % P;
      curinv = curinv * ginv % P;
    }
    auto C = ntt_conv.Multiply(f2, f3);
    ret.resize(P);
    fill(ret.begin(), ret.end(), 0);
    for (int i = 0; i < P; i++) ret[0] += f[i];
    for (int i = 1; i < P; i++) ret[i] += f[0];
    for (T y = 0, cur = 1; y < T(C.size()); y++) {
      ret[cur] += C[y];
      cur = cur * ginv % P;
    }
    for (int i = 0; i < P; i++) ret[i] %= prime;
  }

  T gcd(T a, T b) {
    if (a > b) swap(a, b);
    while (a) {
      T c = a;
      a = b % a;
      b = c;
    }
    return b;
  }
  T modpow(T a, T n, T mod) {
    T ret = 1;
    while (n) {
      if (n & 1) ret = ret * a % mod;
      n >>= 1;
      a = a * a % mod;
    }
    return ret;
  }

  T iscomposite(T a) {
    if (a <= 1) return 1;
    for (T i = 2; i * i <= a; i++) {
      if (a % i == 0) return i;
    }
    return 0;
  }
  T isprimitive(T a, T p) {
    if (a < 2) return false;
    const T q = p - 1;
    for (T i = 2; i * i <= q; i++) {
      if (q % i) continue;
      if (modpow(a, i, p) == 1) return false;
      if (i * i != q && modpow(a, q / i, p) == 1) return false;
    }
    return true;
  }
  T primitive(T p) {
    T a = 2;
    while (isprimitive(a, p) == false) a++;
    return a;
  }
};

void test() {
  clock_t start = clock();
  int N = 97;
  vector<int> x(N - 1);
  rep(i, N - 1) x[i] = rand() % N;
  ArbitaryLengthNTT<int> ntt(N);
  vector<int> ans;
  cout << (ans = ntt.mul(x)) << endl;
  cerr << clock() - start << "ms" << endl;

  int r = ntt.primitive(N);
  vector<int> y(N - 1, 0);
  for (int k = 0; k < N - 1; k++)
    for (int n = 0; n < N - 1; n++) {
      y[k] += x[n] * ntt.modpow(r, n * k, N);
      y[k] %= N;
    }
  // out(y);
  assert(ans == y);
}

namespace fastio {
static constexpr int SZ = 1 << 17;
char ibuf[SZ], obuf[SZ];
int pil = 0, pir = 0, por = 0;

struct Pre {
  char num[40000];
  constexpr Pre() : num() {
    for (int i = 0; i < 10000; i++) {
      int n = i;
      for (int j = 3; j >= 0; j--) {
        num[i * 4 + j] = n % 10 + '0';
        n /= 10;
      }
    }
  }
} constexpr pre;

inline void load() {
  memcpy(ibuf, ibuf + pil, pir - pil);
  pir = pir - pil + fread(ibuf + pir - pil, 1, SZ - pir + pil, stdin);
  pil = 0;
}
inline void flush() {
  fwrite(obuf, 1, por, stdout);
  por = 0;
}

inline void rd(char &c) { c = ibuf[pil++]; }
template <typename T>
inline void rd(T &x) {
  if (pil + 32 > pir) load();
  char c;
  do
    c = ibuf[pil++];
  while (c < '-');
  bool minus = 0;
  if (c == '-') {
    minus = 1;
    c = ibuf[pil++];
  }
  x = 0;
  while (c >= '0') {
    x = x * 10 + (c & 15);
    c = ibuf[pil++];
  }
  if (minus) x = -x;
}
inline void rd() {}
template <typename Head, typename... Tail>
inline void rd(Head &head, Tail &... tail) {
  rd(head);
  rd(tail...);
}

inline void wt(char c) { obuf[por++] = c; }
template <typename T>
inline void wt(T x) {
  if (por > SZ - 32) flush();
  if (!x) {
    obuf[por++] = '0';
    return;
  }
  if (x < 0) {
    obuf[por++] = '-';
    x = -x;
  }
  int i = 12;
  char buf[16];
  while (x >= 10000) {
    memcpy(buf + i, pre.num + (x % 10000) * 4, 4);
    x /= 10000;
    i -= 4;
  }
  int d = x < 100 ? (x < 10 ? 1 : 2) : (x < 1000 ? 3 : 4);
  memcpy(obuf + por, pre.num + x * 4 + 4 - d, d);
  por += d;
  memcpy(obuf + por, buf + i + 4, 12 - i);
  por += 12 - i;
}

inline void wt() {}
template <typename Head, typename... Tail>
inline void wt(Head head, Tail... tail) {
  wt(head);
  wt(tail...);
}
template <typename T>
inline void wtn(T x) {
  wt(x, '\n');
}

struct Dummy {
  Dummy() { atexit(flush); }
} dummy;

}  // namespace fastio
using fastio::rd;
using fastio::wt;
using fastio::wtn;

int main() {
  int p;
  rd(p);
  vi a(p);
  for (auto &x : a) rd(x);
  if (p == 2) {
    cout << a[0] << " " << (a[1] - a[0] + p) % p << endl;
    return 0;
  }
  ArbitaryLengthNTT<int> ntt(p);
  vi ad(p - 1);
  for (int m = 0; m < p - 1; m++) ad[m] = a[ntt.pr[p - 1 - m]];
  vi b = ntt.mul(ad);
  for (auto &x : b) x = x * (p - 1) % p;
  b.pb(b[0]);
  b[p - 1] = (b[p - 1] + p - (b[0] = a[0])) % p;
  rep(i, sz(b)) wt(b[i], " \n"[i == sz(b) - 1]);
}


Measured memory_bytes: 4088