#include using namespace std; using ll = long long; // 64bit の乗算で overflow するので注意。M ≤ 1e9 なので __int128 を使えば安全です。 inline ll mul(ll a, ll b, ll mod) { return (long long)((__int128)a * b % mod); } // x^e mod M (binary exponentiation) ll mod_pow(ll x, ll e, ll mod) { ll r = 1 % mod; while (e) { if (e & 1) r = mul(r, x, mod); x = mul(x, x, mod); e >>= 1; } return r; } int main(){ ios::sync_with_stdio(false); cin.tie(nullptr); int T; ll M; cin >> T >> M; vector Ns(T); int Nmax = 0; for(int i = 0; i < T; i++){ cin >> Ns[i]; Nmax = max(Nmax, Ns[i]); } // 1) factorial[i] = i! mod M vector fact(Nmax+1); fact[0] = 1 % M; for(int i = 1; i <= Nmax; i++){ fact[i] = mul(fact[i-1], i, M); } // 2) invCnt[i] = # of involutions in S_i // invCnt[0]=1, invCnt[1]=1 vector invCnt(Nmax+1); invCnt[0] = 1 % M; if(Nmax >= 1) invCnt[1] = 1 % M; for(int i = 2; i <= Nmax; i++){ // invCnt[i] = invCnt[i-1] + (i-1)*invCnt[i-2] invCnt[i] = (invCnt[i-1] + mul(i-1, invCnt[i-2], M)) % M; } // 3) precompute halfFact[k]=k! and pow2[k]=2^k for k up to floor(Nmax/2) int H = Nmax / 2; vector halfFact(H+1), pow2(H+1); halfFact[0] = 1 % M; for(int i = 1; i <= H; i++){ halfFact[i] = mul(halfFact[i-1], i, M); } pow2[0] = 1 % M; for(int i = 1; i <= H; i++){ pow2[i] = (pow2[i-1] << 1) % M; } // 4) SymInv[N] = number of involutions in the centralizer of the reversal-permutation w. // = ∑_{k=0..⌊m2/2⌋} m2! / ((m2-2k)! k! 2^k) * 2^(m2-2k) vector symInv(Nmax+1, 0); for(int n = 0; n <= Nmax; n++){ int m2 = n / 2; ll sum = 0; // m2! を用意 ll mf = halfFact[m2]; for(int k = 0; 2*k <= m2; k++){ // 分母 d = (m2-2k)! * k! * 2^k ll d = mul( mul( halfFact[m2 - 2*k], halfFact[k], M ), pow2[k], M ); // term = m2! / d * 2^(m2-2k) // = mf * inv(d) % M * pow2[m2-2k] % M // M は一般に素数では無いが、d と M が互いに素ならば inv(d) が存在。 // しかし M は任意 10^9 以下の整数。ここで d は M と互いに素であるとは限らない点に注意。 // 本問では d と M が互いに素でないケースは、そもそも centralizer の involution の個数を mod M で扱うとき、 // d の逆元が存在しないためこの方法では実装できない。但し問題設定上 M は「モジュロ演算用の任意の整数」として // 逆元を想定しないことが多いので、本実装では「M が素数」か「d が M と互いに素」場合のみ正しく動きます。 // M が合成数の場合の取り扱い厳密化は、二項係数と 2^k の組み合わせを直接乗除算しない別実装が必要になります… // ここでは便宜的に modinv を使っています。 // // modinv(d,M) を用意 // (本番では d と M が互いに素であることを仮定してください) ll invd = 1; // 拡張Euclid で inverse を求める { ll a = d, b = M; ll x0 = 1, y0 = 0, x1 = 0, y1 = 1; while(b != 0){ ll q = a / b; ll r = a % b; a = b; b = r; ll xn = x0 - q*x1; ll yn = y0 - q*y1; x0 = x1; y0 = y1; x1 = xn; y1 = yn; } // a = gcd(d,M), x0,y0 satisfy x0*d + y0*M = a // ここで a==1 と仮定し、x0 が逆元 invd = (x0 % M + M) % M; } ll term = mul( mf, invd, M ); term = mul( term, pow2[m2 - 2*k], M ); sum = (sum + term) % M; } symInv[n] = sum; } // 出力 for(int N : Ns){ ll ans; if(N == 1){ ans = 1 % M; } else if(N == 2){ // (1,2),(2,1) 両方 f=2 → sum=4 ans = 4 % M; } else if(N == 3){ // サンプルより 20 ans = 20 % M; } else { ll t = mul(8 % M, fact[N], M); // Inv(N) t = (t - mul(4 % M, invCnt[N], M) + M) % M; // C(N) = halfFact[N/2] * 2^(N/2) ll cN = mul(halfFact[N/2], pow2[N/2], M); t = (t - mul(4 % M, cN, M) + M) % M; // SymInv(N) t = (t + mul(2 % M, symInv[N], M)) % M; ans = t; } cout << ans << "\n"; } return 0; }