#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
#ifdef NyaanDebug
  #include "NyaanDebug.h"
  #define trc(...) do { cout << #__VA_ARGS__ << " = "; dbg_out(__VA_ARGS__);} while(0)
  #define trca(v,N) do { cout << #v << " = "; array_out(v , N);cout << endl;} while(0)
#else
  #define trc(...)
  #define trca(...)
#endif
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);}

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;
    //trc();trc(p_primitive); trc(pr);
  }

  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);
    //trc("CooleyTukey" , N , P);
    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);
    //trc("Rader" , P);
    T g = primitive(P);
    T ginv = modpow(g , P - 2 , P);
    //trc(f , g , ginv);
    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);
    //trc(f2); trc(f3); trc(C);
    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;
    //trc(ret);
  }


  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);
}

int main(){
  ini(p); vi a(p); in(a);
  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);
  //trc(b);
  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;
  out(b);
}


Measured memory_bytes: 640