#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());
//////////////////////////////////////////

//BEGIN CUT HERE
constexpr int bmds(int x){
  const int v[] = {1012924417, 924844033, 998244353,
                   897581057, 645922817};
  return v[x];
}
constexpr int brts(int x){
  const int v[] = {5, 5, 3, 3, 3};
  return v[x];
}


template<int X>
struct NTT{
  static constexpr int md = bmds(X);
  static constexpr int rt = brts(X);

  inline int add(int a,int b){
    a+=b;
    if(a>=md) a-=md;
    return a;
  }

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

  inline int pow(int a,int b){
    int res=1;
    while(b){
      if(b&1) res=mul(res,a);
      a=mul(a,a);
      b>>=1;
    }
    return res;
  }

  inline int inv(int x){
    return pow(x,md-2);
  }

  // assume md % 4 = 1
  // if md % 4 == 3, then x = a^{(md+1)/4}
  inline int sqrt(int a){
    if(a==0) return 0;
    if(pow(a,(md-1)/2)!=1) return -1;
    int q=md-1,m=0;
    while(~q&1) q>>=1,m++;
    mt19937 mt;
    int z=mt()%md;
    while(pow(z,(md-1)/2)!=md-1) z=mt()%md;
    int c=pow(z,q),t=pow(a,q),r=pow(a,(q+1)/2);
    while(m>1){
      if(pow(t,1<<(m-2))!=1)
        r=mul(r,c),t=mul(t,mul(c,c));
      c=mul(c,c);
      m--;
    }
    return r;
  }

  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].empty()) continue;
      int w=pow(rt,(md-1)/(i<<1));
      int rw=inv(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);
      }
    }
  }

  void ntt(vector<int> &a,bool f,int n=-1){
    if(n==-1) n=a.size();
    assert((n&(n-1))==0);

    for(int i=0,j=1;j+1<n;j++){
      for(int k=n>>1;k>(i^=k);k>>=1);
      if(i>j) swap(a[i],a[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 z=mul(a[i+j+k],f?rrts[i][k]:rts[i][k]);
          a[i+j+k]=add(a[j+k],md-z);
          a[j+k]=add(a[j+k],z);
        }
      }
    }

    if(f){
      int tmp=inv(n);
      for(int i=0;i<n;i++) a[i]=mul(a[i],tmp);
    }
  }

  vector<int> add(vector<int> as,vector<int> bs){
    int sz=max(as.size(),bs.size());
    vector<int> cs(sz,0);
    for(int i=0;i<(int)as.size();i++) cs[i]=add(cs[i],as[i]);
    for(int i=0;i<(int)bs.size();i++) cs[i]=add(cs[i],bs[i]);
    return cs;
  }

  vector<int> sub(vector<int> as,vector<int> bs){
    int sz=max(as.size(),bs.size());
    vector<int> cs(sz,0);
    for(int i=0;i<(int)as.size();i++) cs[i]=add(cs[i],as[i]);
    for(int i=0;i<(int)bs.size();i++) cs[i]=add(cs[i],md-bs[i]);
    return cs;
  }

  vector<int> multiply(vector<int> as,vector<int> bs){
    int need=as.size()+bs.size()-1;
    int sz=1;
    while(sz<need) sz<<=1;
    ensure_base(sz);

    vector<int> f(sz),g(sz);
    for(int i=0;i<(int)as.size();i++) f[i]=as[i];
    for(int i=0;i<(int)bs.size();i++) g[i]=bs[i];
    ntt(f,0);ntt(g,0);
    for(int i=0;i<sz;i++) f[i]=mul(f[i],g[i]);
    ntt(f,1);

    f.resize(need);
    return f;
  }

  vector<int> divide(vector<int> as,vector<int> bs){
    assert(bs!=vector<int>(bs.size(),0));
    if(as==vector<int>(as.size(),0)) return {0};
    assert(as.size()>=bs.size());

    if(bs[0]==0){
      reverse(as.begin(),as.end());
      reverse(bs.begin(),bs.end());
      while(bs.back()==0){
        assert(as.back()==0);
        as.pop_back();
        bs.pop_back();
      }
      reverse(as.begin(),as.end());
      reverse(bs.begin(),bs.end());
    }

    int need=as.size()-bs.size()+1;
    as.resize(need);

    int sz=1;
    vector<int> rs({inv(bs[0])});
    while(sz<need){
      sz<<=1;
      vector<int> ts(min(sz,(int)bs.size()));
      for(int i=0;i<(int)ts.size();i++) ts[i]=bs[i];
      rs=sub(add(rs,rs),multiply(multiply(rs,rs),ts));
      rs.resize(sz);
    }

    while(as.back()==0) as.pop_back();
    while(rs.back()==0) rs.pop_back();
    auto cs=multiply(as,rs);
    cs.resize(need,0);
    return cs;
  }

  vector<int> sqrt(vector<int> as){
    if(as==vector<int>(as.size(),0)) return {0};

    int dg=0;
    if(as[0]==0){
      reverse(as.begin(),as.end());
      while(as.back()==0){
        dg++;
        as.pop_back();
        assert(as.back()==0);
        as.pop_back();
      }
      reverse(as.begin(),as.end());
    }

    int sz=1,inv2=inv(2);
    vector<int> ss({sqrt(as[0])});
    while(sz<(int)as.size()){
      sz<<=1;
      vector<int> ts(min(sz+sz/2-1,(int)as.size()));
      for(int i=0;i<(int)ts.size();i++) ts[i]=as[i];
      ss=add(ss,divide(ts,ss));
      ss.resize(sz);
      for(int &x:ss) x=mul(x,inv2);
    }

    if(dg){
      reverse(ss.begin(),ss.end());
      for(int i=0;i<dg;i++) ss.emplace_back(0);
      reverse(ss.begin(),ss.end());
    }
    return ss;
  }
};
//END CUT HERE
NTT< 0 > 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 * p] * 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];
      }
    }
    
  }

  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];
      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