Problem:
Problem J:
多項式の解の個数
きたまさ君は大学でさまざまな変換について研究している。最近、きたまさ君が興味を持っている変換は次のようなものである。 N+1個の整数 a
0
, ..., a
N
を固定し、整数 z を入力とする。また P を素数とする。
t = ( a
N
z
N
+ a
N-1
z
N-1
+ ... + a
2
z
2
+ a
1
z + a
0
) mod P
きたまさ君はこの変換によって t = 0 になってしまう z がいくつもあることに気がついた。 そこで、きたまさ君は友人でありスーパープログラマーでもあるあなたに、変換後に t = 0 になる z が 0〜P-1 にいくつあるかを計算してもらうことにした。
Input
入力は次の形式で与えられる。
N P
a
0
a
1
... a
N
入力の1行目には整数Nと素数Pがスペース文字で区切られて与えられる。これらは、問題文で与えられたとおりである。 0 ≤ N ≤ 100, 2 ≤ P ≤ 10
9
を満たす。
次の1行には a
0
〜a
N
がスペース文字で区切られて与えられる。これらは |a
i
| ≤ 10
9
を満たす整数である。また a
N
≠ 0 である。
Output
変換後に0になるような z (0 ≤ z < P) の個数を出力せよ。
Notes on Test Cases
上記入力形式で複数のデータセットが与えられます。各データセットに対して上記出力形式で出力を行うプログラムを作成して下さい。
N, P がともに 0 のとき入力の終わりを示します。
Sample Input
2 3
1 2 1
2 3
1 2 6
0 0
Output for Sample Input
1
1

Submitted solutions:

code_snippet: #include <bits/stdc++.h>
using namespace std;

// min non-negative i such that n <= 2^i
int ceil_pow2(int n) {
    int i = 0;
    while ((1U << i) < (unsigned int)(n)) i++;
    return i;
}

// min non-negative i such that (x & (1 << i)) != 0
int bsf(int x) { return __builtin_ctz(x); }
int bsf(unsigned int x) { return __builtin_ctz(x); }
int bsf(long long x) { return __builtin_ctzll(x); }
int bsf(unsigned long long x) { return __builtin_ctzll(x); }

// safe mod
template<class T_VAL, class T_MOD>
constexpr T_VAL safe_mod(T_VAL a, T_MOD m) {
    assert(m > 0);
    a %= m;
    if (a < 0) a += m;
    return a;
}

// mod pow
template<class T_VAL, class T_MOD>
constexpr T_VAL mod_pow(T_VAL a, T_VAL n, T_MOD m) {
    T_VAL res = 1;
    while (n > 0) {
        if (n % 2 == 1) res = res * a % m;
        a = a * a % m;
        n >>= 1;
    }
    return res;
}

// mod inv
template<class T_VAL, class T_MOD>
constexpr T_VAL mod_inv(T_VAL a, T_MOD m) {
    T_VAL b = m, u = 1, v = 0;
    while (b > 0) {
        T_VAL t = a / b;
        a -= t * b, swap(a, b);
        u -= t * v, swap(u, v);
    }
    u %= m;
    if (u < 0) u += m;
    return u;
}

// modint
template<int MOD = 998244353, bool PRIME = true> struct Fp {
    // inner value
    unsigned int val;
    
    // constructor
    constexpr Fp() : val(0) { }
    template<std::signed_integral T> constexpr Fp(T v) {
        long long tmp = (long long)(v % (long long)(get_umod()));
        if (tmp < 0) tmp += get_umod();
        val = (unsigned int)(tmp);
    }
    template<std::unsigned_integral T> constexpr Fp(T v) {
        val = (unsigned int)(v % get_umod());
    }
    constexpr long long get() const { return val; }
    constexpr static int get_mod() { return MOD; }
    constexpr static unsigned int get_umod() { return MOD; }
    
    // arithmetic operators
    constexpr Fp operator + () const { return Fp(*this); }
    constexpr Fp operator - () const { return Fp() - Fp(*this); }
    constexpr Fp operator + (const Fp &r) const { return Fp(*this) += r; }
    constexpr Fp operator - (const Fp &r) const { return Fp(*this) -= r; }
    constexpr Fp operator * (const Fp &r) const { return Fp(*this) *= r; }
    constexpr Fp operator / (const Fp &r) const { return Fp(*this) /= r; }
    constexpr Fp& operator += (const Fp &r) {
        val += r.val;
        if (val >= get_umod()) val -= get_umod();
        return *this;
    }
    constexpr Fp& operator -= (const Fp &r) {
        val -= r.val;
        if (val >= get_umod()) val += get_umod();
        return *this;
    }
    constexpr Fp& operator *= (const Fp &r) {
        unsigned long long tmp = val;
        tmp *= r.val;
        val = (unsigned int)(tmp % get_umod());
        return *this;
    }
    constexpr Fp& operator /= (const Fp &r) {
        return *this = *this * r.inv(); 
    }
    constexpr Fp pow(long long n) const {
        assert(n >= 0);
        Fp res(1), mul(*this);
        while (n) {
            if (n & 1) res *= mul;
            mul *= mul;
            n >>= 1;
        }
        return res;
    }
    constexpr Fp inv() const {
        if (PRIME) {
            assert(val);
            return pow(get_umod() - 2);
        } else {
            assert(val);
            return mod_inv((long long)(val), get_umod());
        }
    }

    // other operators
    constexpr bool operator == (const Fp &r) const {
        return this->val == r.val;
    }
    constexpr bool operator != (const Fp &r) const {
        return this->val != r.val;
    }
    constexpr bool operator < (const Fp &r) const {
        return this->val < r.val;
    }
    constexpr bool operator > (const Fp &r) const {
        return this->val > r.val;
    }
    constexpr bool operator <= (const Fp &r) const {
        return this->val <= r.val;
    }
    constexpr bool operator >= (const Fp &r) const {
        return this->val >= r.val;
    }
    constexpr Fp& operator ++ () {
        ++val;
        if (val == get_umod()) val = 0;
        return *this;
    }
    constexpr Fp& operator -- () {
        if (val == 0) val = get_umod();
        --val;
        return *this;
    }
    constexpr Fp operator ++ (int) {
        Fp res = *this;
        ++*this;
        return res;
    }
    constexpr Fp operator -- (int) {
        Fp res = *this;
        --*this;
        return res;
    }
    friend constexpr istream& operator >> (istream &is, Fp<MOD> &x) {
        long long tmp = 1;
        is >> tmp;
        tmp = tmp % (long long)(get_umod());
        if (tmp < 0) tmp += get_umod();
        x.val = (unsigned int)(tmp);
        return is;
    }
    friend constexpr ostream& operator << (ostream &os, const Fp<MOD> &x) {
        return os << x.val;
    }
    friend constexpr Fp<MOD> pow(const Fp<MOD> &r, long long n) {
        return r.pow(n);
    }
    friend constexpr Fp<MOD> inv(const Fp<MOD> &r) {
        return r.inv();
    }
};

// dynamic modint
struct DynamicModint {
    using mint = DynamicModint;
    
    // static menber
    static int MOD;
    
    // inner value
    unsigned int val;
    
    // constructor
    DynamicModint() : val(0) { }
    template<std::signed_integral T> DynamicModint(T v) {
        long long tmp = (long long)(v % (long long)(get_umod()));
        if (tmp < 0) tmp += get_umod();
        val = (unsigned int)(tmp);
    }
    template<std::unsigned_integral T> DynamicModint(T v) {
        val = (unsigned int)(v % get_umod());
    }
    long long get() const { return val; }
    static int get_mod() { return MOD; }
    static unsigned int get_umod() { return MOD; }
    static void set_mod(int mod) { MOD = mod; }
    
    // arithmetic operators
    mint operator + () const { return mint(*this); }
    mint operator - () const { return mint() - mint(*this); }
    mint operator + (const mint &r) const { return mint(*this) += r; }
    mint operator - (const mint &r) const { return mint(*this) -= r; }
    mint operator * (const mint &r) const { return mint(*this) *= r; }
    mint operator / (const mint &r) const { return mint(*this) /= r; }
    mint& operator += (const mint &r) {
        val += r.val;
        if (val >= get_umod()) val -= get_umod();
        return *this;
    }
    mint& operator -= (const mint &r) {
        val -= r.val;
        if (val >= get_umod()) val += get_umod();
        return *this;
    }
    mint& operator *= (const mint &r) {
        unsigned long long tmp = val;
        tmp *= r.val;
        val = (unsigned int)(tmp % get_umod());
        return *this;
    }
    mint& operator /= (const mint &r) {
        return *this = *this * r.inv(); 
    }
    mint pow(long long n) const {
        assert(n >= 0);
        mint res(1), mul(*this);
        while (n) {
            if (n & 1) res *= mul;
            mul *= mul;
            n >>= 1;
        }
        return res;
    }
    mint inv() const {
        assert(val);
        return mod_inv((long long)(val), get_umod());
    }

    // other operators
    bool operator == (const mint &r) const {
        return this->val == r.val;
    }
    bool operator != (const mint &r) const {
        return this->val != r.val;
    }
    bool operator < (const mint &r) const {
        return this->val < r.val;
    }
    bool operator > (const mint &r) const {
        return this->val > r.val;
    }
    bool operator <= (const mint &r) const {
        return this->val <= r.val;
    }
    bool operator >= (const mint &r) const {
        return this->val >= r.val;
    }
    mint& operator ++ () {
        ++val;
        if (val == get_umod()) val = 0;
        return *this;
    }
    mint& operator -- () {
        if (val == 0) val = get_umod();
        --val;
        return *this;
    }
    mint operator ++ (int) {
        mint res = *this;
        ++*this;
        return res;
    }
    mint operator -- (int) {
        mint res = *this;
        --*this;
        return res;
    }
    friend istream& operator >> (istream &is, mint &x) {
        long long tmp = 1;
        is >> tmp;
        tmp = tmp % (long long)(get_umod());
        if (tmp < 0) tmp += get_umod();
        x.val = (unsigned int)(tmp);
        return is;
    }
    friend ostream& operator << (ostream &os, const mint &x) {
        return os << x.val;
    }
    friend mint pow(const mint &r, long long n) {
        return r.pow(n);
    }
    friend mint inv(const mint &r) {
        return r.inv();
    }
};
int DynamicModint::MOD;

// Binomial coefficient
template<class mint> struct BiCoef {
    vector<mint> fact_, inv_, finv_;
    constexpr BiCoef() {}
    constexpr BiCoef(int n) : fact_(n, 1), inv_(n, 1), finv_(n, 1) {
        init(n);
    }
    constexpr void init(int n) {
        fact_.assign(n, 1), inv_.assign(n, 1), finv_.assign(n, 1);
        int MOD = fact_[0].get_mod();
        for(int i = 2; i < n; i++){
            fact_[i] = fact_[i-1] * i;
            inv_[i] = -inv_[MOD%i] * (MOD/i);
            finv_[i] = finv_[i-1] * inv_[i];
        }
    }
    constexpr mint com(int n, int k) const {
        if (n < k || n < 0 || k < 0) return 0;
        return fact_[n] * finv_[k] * finv_[n-k];
    }
    constexpr mint fact(int n) const {
        if (n < 0) return 0;
        return fact_[n];
    }
    constexpr mint inv(int n) const {
        if (n < 0) return 0;
        return inv_[n];
    }
    constexpr mint finv(int n) const {
        if (n < 0) return 0;
        return finv_[n];
    }
};

// calc primitive root
constexpr int calc_primitive_root(long long m) {
    if (m == 1) return -1;
    if (m == 2) return 1;
    if (m == 998244353) return 3;
    if (m == 167772161) return 3;
    if (m == 469762049) return 3;
    if (m == 754974721) return 11;
    if (m == 645922817) return 3;
    if (m == 897581057) return 3;
    return -1;
}

// NTT setup
template<class mint, int MOD = mint::get_mod(), int g = calc_primitive_root(mint::get_mod())>
struct ntt_setup {
    static constexpr int bsf_constexpr(unsigned int x) {
        int i = 0;
        while (!(x & (1 << i))) i++;
        return i;
    };

    static constexpr int rank = bsf_constexpr(MOD - 1);
    array<mint, rank + 1> root, iroot;  // root[i]^(2^i) = 1, root[i] * iroot[i] = 1
    array<mint, max(0, rank - 1)> rate2, irate2;
    array<mint, max(0, rank - 2)> rate3, irate3;

    ntt_setup() {
        root[rank] = mint(g).pow((MOD - 1) >> rank);
        iroot[rank] = root[rank].inv();
        for (int i = rank - 1; i >= 0; i--) {
            root[i] = root[i + 1] * root[i + 1];
            iroot[i] = iroot[i + 1] * iroot[i + 1];
        }
        mint prod = 1, iprod = 1;
        for (int i = 0; i < rank - 1; i++) {
            rate2[i] = root[i + 2] * prod;
            irate2[i] = iroot[i + 2] * iprod;
            prod *= iroot[i + 2];
            iprod *= root[i + 2];
        }
        prod = 1, iprod = 1;
        for (int i = 0; i < rank - 2; i++) {
            rate3[i] = root[i + 3] * prod;
            irate3[i] = iroot[i + 3] * iprod;
            prod *= iroot[i + 3];
            iprod *= root[i + 3];
        }
    }
};

// NTT transformation
template<class mint, int MOD = mint::get_mod()> 
void ntt_trans(vector<mint> &v) {
    int n = (int)v.size();
    int h = ceil_pow2(n);
    static const ntt_setup<mint> setup;

    int len = 0;
    while (len < h) {
        if (h - len == 1) {
            int p = 1 << (h - len - 1);
            mint rot = 1;
            for (int s = 0; s < (1 << len); s++) {
                int offset = s << (h - len);
                for (int i = 0; i < p; i++) {
                    auto l = v[i + offset];
                    auto r = v[i + offset + p] * rot;
                    v[i + offset] = l + r;
                    v[i + offset + p] = l - r;
                }
                if (s + 1 != (1 << len)) {
                    rot *= setup.rate2[bsf(~(unsigned int)(s))];
                }
            }
            len++;
        } else {
            int p = 1 << (h - len - 2);
            mint rot = 1, imag = setup.root[2];
            for (int s = 0; s < (1 << len); s++) {
                mint rot2 = rot * rot, rot3 = rot2 * rot;
                int offset = s << (h - len);
                for (int i = 0; i < p; i++) {
                    auto mod2 = 1ULL * MOD * MOD;
                    auto a0 = 1ULL * v[i + offset].val;
                    auto a1 = 1ULL * v[i + offset + p].val * rot.val;
                    auto a2 = 1ULL * v[i + offset + p * 2].val * rot2.val;
                    auto a3 = 1ULL * v[i + offset + p * 3].val * rot3.val;
                    auto tmp = 1ULL * mint(a1 + mod2 - a3).val * imag.val;
                    auto na2 = mod2 - a2;
                    v[i + offset] = a0 + a2 + a1 + a3;
                    v[i + offset + p] = a0 + a2 + (mod2 * 2 - (a1 + a3));
                    v[i + offset + p * 2] = a0 + na2 + tmp;
                    v[i + offset + p * 3] = a0 + na2 + (mod2 - tmp);
                }
                if (s + 1 != (1 << len)) {
                    rot *= setup.rate3[bsf(~(unsigned int)(s))];
                }
            }
            len += 2;
        }
    }
}

// NTT inv-transformation
template<class mint, int MOD = mint::get_mod()> 
void ntt_trans_inv(vector<mint> &v) {
    int n = (int)v.size();
    int h = ceil_pow2(n);
    static const ntt_setup<mint> setup;

    int len = h;
    while (len) {
        if (len == 1) {
            int p = 1 << (h - len);
            mint irot = 1;
            for (int s = 0; s < (1 << (len - 1)); s++) {
                int offset = s << (h - len + 1);
                for (int i = 0; i < p; i++) {
                    auto l = v[i + offset];
                    auto r = v[i + offset + p];
                    v[i + offset] = l + r;
                    v[i + offset + p] = (unsigned long long)((long long)(MOD) + l.val - r.val) * irot.val;
                }
                if (s + 1 != (1 << (len - 1))) {
                    irot *= setup.irate2[bsf(~(unsigned int)(s))];
                }
            }
            len--;
        } else {
            int p = 1 << (h - len);
            mint irot = 1, iimag = setup.iroot[2];
            for (int s = 0; s < (1 << (len - 2)); s++) {
                mint irot2 = irot * irot, irot3 = irot2 * irot;
                int offset = s << (h - len + 2);
                for (int i = 0; i < p; i++) {
                    auto a0 = 1ULL * v[i + offset].val;
                    auto a1 = 1ULL * v[i + offset + p].val;
                    auto a2 = 1ULL * v[i + offset + p * 2].val;
                    auto a3 = 1ULL * v[i + offset + p * 3].val;
                    auto tmp = 1ULL * mint((MOD + a2 - a3) * iimag.val).val;
                    v[i + offset] = a0 + a1 + a2 + a3;
                    v[i + offset + p] = (a0 + (MOD - a1) + tmp) * irot.val;
                    v[i + offset + p * 2] = (a0 + a1 + (MOD - a2) + (MOD - a3)) * irot2.val;
                    v[i + offset + p * 3] = (a0 + (MOD - a1) + (MOD - tmp)) * irot3.val;
                }
                if (s + 1 != (1 << (len - 2))) {
                    irot *= setup.irate3[bsf(~(unsigned int)(s))];
                }
            }
            len -= 2;
        }
    }
    mint in = mint(n).inv();
    for (int i = 0; i < n; i++) v[i] *= in;
}

// naive convolution
template<class T>
vector<T> sub_convolution_naive(const vector<T> &a, const vector<T> &b) {
    int n = (int)a.size(), m = (int)b.size();
    vector<T> res(n + m - 1);
    if (n < m) {
        for (int j = 0; j < m; j++) for (int i = 0; i < n; i++) res[i + j] += a[i] * b[j];
    } else {
        for (int i = 0; i < n; i++) for (int j = 0; j < m; j++) res[i + j] += a[i] * b[j];
    }
    return res;
}

// ntt convolution
template<class mint>
vector<mint> sub_convolution_ntt(vector<mint> a, vector<mint> b) {
    int MOD = mint::get_mod();
    int n = (int)a.size(), m = (int)b.size();
    if (!n || !m) return {};
    int z = (int)bit_ceil((unsigned int)(n + m - 1));
    assert((MOD - 1) % z == 0);
    a.resize(z), b.resize(z);
    ntt_trans(a), ntt_trans(b);
    for (int i = 0; i < z; i++) a[i] *= b[i];
    ntt_trans_inv(a);
    a.resize(n + m - 1);
    return a;
}

// convolution in general mod
template<class mint>
vector<mint> convolution(const vector<mint> &a, const vector<mint> &b) {
    int n = (int)a.size(), m = (int)b.size();
    if (!n || !m) return {};
    if (min(n, m) <= 60) return sub_convolution_naive(std::move(a), std::move(b));
    if constexpr (std::is_same_v<mint, Fp<998244353>>) return sub_convolution_ntt(a, b);

    static constexpr int MOD0 = 754974721;  // 2^24
    static constexpr int MOD1 = 167772161;  // 2^25
    static constexpr int MOD2 = 469762049;  // 2^26
    using mint0 = Fp<MOD0>;
    using mint1 = Fp<MOD1>;
    using mint2 = Fp<MOD2>;
    static const mint1 imod0 = 95869806; // modinv(MOD0, MOD1);
    static const mint2 imod1 = 104391568; // modinv(MOD1, MOD2);
    static const mint2 imod01 = 187290749; // imod1 / MOD0;

    vector<mint0> a0(n, 0), b0(m, 0);
    vector<mint1> a1(n, 0), b1(m, 0);
    vector<mint2> a2(n, 0), b2(m, 0);
    for (int i = 0; i < n; ++i) a0[i] = a[i].val, a1[i] = a[i].val, a2[i] = a[i].val;
    for (int i = 0; i < m; ++i) b0[i] = b[i].val, b1[i] = b[i].val, b2[i] = b[i].val;
    auto c0 = sub_convolution_ntt(std::move(a0), std::move(b0));
    auto c1 = sub_convolution_ntt(std::move(a1), std::move(b1));
    auto c2 = sub_convolution_ntt(std::move(a2), std::move(b2));

    vector<mint> res(n + m - 1);
    mint mod0 = MOD0, mod01 = mod0 * MOD1;
    for (int i = 0; i < n + m - 1; ++i) {
        unsigned int y0 = c0[i].val;
        unsigned int y1 = (imod0 * (c1[i] - y0)).val;
        unsigned int y2 = (imod01 * (c2[i] - y0) - imod1 * y1).val;
        res[i] = mod01 * y2 + mod0 * y1 + y0;
    }
    return res;
}


//------------------------------//
// FPS
//------------------------------//

// Formal Power Series
template<class mint> struct FPS : vector<mint> {
    static const int SPARSE_BOARDER = 50;
    using vector<mint>::vector;
 
    // constructor
    constexpr FPS(const vector<mint> &r) : vector<mint>(r) {}
 
    // core operator
    constexpr FPS pre(int siz) const {
        return FPS(begin(*this), begin(*this) + min((int)this->size(), siz));
    }
    constexpr FPS rev() const {
        FPS res = *this;
        reverse(begin(res), end(res));
        return res;
    }
    constexpr FPS& normalize() {
        while (!this->empty() && this->back() == 0) this->pop_back();
        return *this;
    }
    constexpr mint eval(const mint &v) {
        mint res = 0;
        for (int i = (int)this->size()-1; i >= 0; --i) {
            res *= v;
            res += (*this)[i];
        }
        return res;
    }
    constexpr int count_terms() const {
        int res = 0;
        for (int i = 0; i < (int)this->size(); i++) if ((*this)[i] != mint(0)) res++;
        return res;
    }
 
    // basic operator
    constexpr FPS operator - () const noexcept {
        FPS res = (*this);
        for (int i = 0; i < (int)res.size(); ++i) res[i] = -res[i];
        return res;
    }
    constexpr FPS operator + (const mint &v) const { return FPS(*this) += v; }
    constexpr FPS operator + (const FPS &r) const { return FPS(*this) += r; }
    constexpr FPS operator - (const mint &v) const { return FPS(*this) -= v; }
    constexpr FPS operator - (const FPS &r) const { return FPS(*this) -= r; }
    constexpr FPS operator * (const mint &v) const { return FPS(*this) *= v; }
    constexpr FPS operator * (const FPS &r) const { return FPS(*this) *= r; }
    constexpr FPS operator / (const mint &v) const { return FPS(*this) /= v; }
    constexpr FPS operator / (const FPS &r) const { return FPS(*this) /= r; }
    constexpr FPS operator % (const FPS &r) const { return FPS(*this) %= r; }
    constexpr FPS operator << (int x) const { return FPS(*this) <<= x; }
    constexpr FPS operator >> (int x) const { return FPS(*this) >>= x; }
    constexpr FPS& operator += (const mint &v) {
        if (this->empty()) this->reserve(1), this->resize(1);
        (*this)[0] += v;
        return *this;
    }
    constexpr FPS& operator += (const FPS &r) {
        if (r.size() > this->size()) this->reserve(r.size()), this->resize(r.size());
        for (int i = 0; i < (int)r.size(); ++i) (*this)[i] += r[i];
        return this->normalize();
    }
    constexpr FPS& operator -= (const mint &v) {
        if (this->empty()) this->reserve(1), this->resize(1);
        (*this)[0] -= v;
        return *this;
    }
    constexpr FPS& operator -= (const FPS &r) {
        if (r.size() > this->size()) this->reserve(r.size()), this->resize(r.size());
        for (int i = 0; i < (int)r.size(); ++i) (*this)[i] -= r[i];
        return this->normalize();
    }
    constexpr FPS& operator *= (const mint &v) {
        for (int i = 0; i < (int)this->size(); ++i) (*this)[i] *= v;
        return *this;
    }
    constexpr FPS& operator *= (const FPS &r) {
        return *this = convolution((*this), r);
    }
    constexpr FPS& operator /= (const mint &v) {
        assert(v != 0);
        mint iv = v.inv();
        for (int i = 0; i < (int)this->size(); ++i) (*this)[i] *= iv;
        return *this;
    }
    
    // division, r must be normalized (r.back() must not be 0)
    constexpr FPS& operator /= (const FPS &r) {
        assert(!r.empty());
        assert(r.back() != 0);
        this->normalize();
        if (this->size() < r.size()) {
            this->clear();
            return *this;
        }
        int need = (int)this->size() - (int)r.size() + 1;
        *this = (rev().pre(need) * r.rev().inv(need)).pre(need).rev();
        return *this;
    }
    constexpr FPS& operator %= (const FPS &r) {
        assert(!r.empty());
        assert(r.back() != 0);
        this->normalize();
        FPS q = (*this) / r;
        return *this -= q * r;
    }
    constexpr FPS& operator <<= (int x) {
        FPS res(x, 0);
        res.insert(res.end(), begin(*this), end(*this));
        return *this = res;
    }
    constexpr FPS& operator >>= (int x) {
        FPS res;
        res.insert(res.end(), begin(*this) + x, end(*this));
        return *this = res;
    }

    // advanced operation
    // df/dx
    constexpr FPS diff() const {
        int n = (int)this->size();
        if (n <= 0) return FPS();
        FPS res(n-1);
        for (int i = 1; i < n; ++i) res[i-1] = (*this)[i] * i;
        return res;
    }
    
    // \int f dx
    constexpr FPS integral() const {
        int n = (int)this->size();
        FPS res(n+1, 0);
        for (int i = 0; i < n; ++i) res[i+1] = (*this)[i] / (i+1);
        return res;
    }
    
    // inv(f), f[0] must not be 0
    constexpr FPS inv(int deg = -1) const {
        if (count_terms() <= SPARSE_BOARDER) return inv_sparse(deg);
        if constexpr (std::is_same_v<mint, Fp<998244353>>) return inv_ntt_friendly(deg);
        assert(this->size() >= 1 && (*this)[0] != 0);
        if (deg < 0) deg = (int)this->size();
        FPS res({mint(1) / (*this)[0]});
        for (int d = 1; d < deg; d <<= 1) {
            res = (res + res - res * res * pre(d << 1)).pre(d << 1);
        }
        res.resize(deg);
        return res;
    }
    constexpr FPS inv_ntt_friendly(int deg = -1) const {
        assert(this->size() >= 1 && (*this)[0] != 0);
        if (deg < 0) deg = (int)this->size();
        FPS res(deg);
        res[0] = mint(1) / (*this)[0];
        for (int d = 1; d < deg; d <<= 1) {
            FPS g(d * 2), h(d * 2);
            mint iv = mint(d * 2).inv();
            for (int i = 0; i < min((int)this->size(), d * 2); i++) g[i] = (*this)[i];
            for (int i = 0; i < d; i++) h[i] = res[i];
            ntt_trans(g), ntt_trans(h);
            for (int i = 0; i < d * 2; i++) g[i] *= h[i];
            ntt_trans_inv(g);
            for (int i = 0; i < d; i++) g[i] = 0;
            ntt_trans(g);
            for (int i = 0; i < d * 2; i++) g[i] *= h[i];
            ntt_trans_inv(g);
            for (int i = d; i < min(deg, d * 2); i++) res[i] = -g[i];
        }
        return res.pre(deg);
    }
    constexpr FPS inv_sparse(int deg = -1) const {
        assert(this->size() >= 1 && (*this)[0] != 0);
        if (deg < 0) deg = (int)this->size();
        vector<pair<int, mint>> dat;
        for (int i = 1; i < (int)this->size(); i++) if ((*this)[i] != mint(0)) {
            dat.emplace_back(i, (*this)[i]);
        }
        vector<mint> res(deg);
        res[0] = (*this)[0].inv();
        for (int i = 1; i < deg; i++) {
            mint r = 0;
            for (auto &&[k, val] : dat) {
                if (k > i) break;
                r -= val * res[i - k];
            }
            res[i] = r * res[0];
        }
        return res;
    }
    
    // friend operators
    friend constexpr FPS inv(const FPS &f, int deg = -1) { return f.inv(deg); }
};

// find f(x)^n mod g(x)
template<class mint, class T_VAL = long long> 
FPS<mint> mod_pow(const FPS<mint> &f, T_VAL e, const FPS<mint> &mod) {
    assert(!mod.empty());
    auto iv = mod.rev().inv();
    auto calc_quo = [&](const FPS<mint> &pol) -> FPS<mint> {
        if (pol.size() < mod.size()) return FPS<mint>();
        int deg = (int)pol.size() - (int)mod.size() + 1;
        return (pol.rev().pre(deg) * iv.pre(deg)).pre(deg).rev();
    };
    FPS<mint> res{1}, b(f);
    while (e) {
        if (e & 1) res *= b, res -= calc_quo(res) * mod;
        b *= b;
        b -= calc_quo(b) * mod;
        e >>= 1;
        assert(b.size() + 1 <= mod.size());
        assert(res.size() + 1 <= mod.size());
    }
    return res;
}

// polynomial gcd
template<class mint>
struct MatrixFPS22 {
    FPS<mint> a00, a01, a10, a11;
    MatrixFPS22() {}
    MatrixFPS22(const FPS<mint> &a00, const FPS<mint> &a01, const FPS<mint> &a10, const FPS<mint> &a11)
        : a00(a00), a01(a01), a10(a10), a11(a11) {}

    MatrixFPS22 &operator *= (const MatrixFPS22 &r) {
        FPS<mint> A00 = a00 * r.a00 + a01 * r.a10;
        FPS<mint> A01 = a00 * r.a01 + a01 * r.a11;
        FPS<mint> A10 = a10 * r.a00 + a11 * r.a10;
        FPS<mint> A11 = a10 * r.a01 + a11 * r.a11;
        swap(A00, a00), swap(A01, a01), swap(A10, a10), swap(A11, a11);
        return *this;
    }
    static MatrixFPS22 get_identity() { 
        return MatrixFPS22(FPS<mint>{mint(1)}, FPS<mint>(), FPS<mint>(), FPS<mint>{mint(1)});
    }
    MatrixFPS22 operator * (const MatrixFPS22 &r) const { return MatrixFPS22(*this) *= r; }
};

template<class mint> pair<FPS<mint>, FPS<mint>> operator * (
const MatrixFPS22<mint> &m, const pair<FPS<mint>, FPS<mint>> &a) {
    FPS<mint> b0 = m.a00 * a.first + m.a01 * a.second;
    FPS<mint> b1 = m.a10 * a.first + m.a11 * a.second;
    return {b0, b1};
}

template<class mint> MatrixFPS22<mint> mat_poly_half_gcd(pair<FPS<mint>, FPS<mint>> p) {
    auto naive_gcd = [](MatrixFPS22<mint> &m, pair<FPS<mint>, FPS<mint>> &p) -> void {
        FPS<mint> q = p.first / p.second, r = p.first - p.second * q;
        FPS<mint> b10 = m.a00 - m.a10 * q, b11 = m.a01 - m.a11 * q;
        swap(b10, m.a10), swap(b11, m.a11), swap(b10, m.a00), swap(b11, m.a01);
        p = {p.second, r};
    };
    int N = p.first.size(), M = p.second.size(), K = (N + 1) / 2;
    if (M <= K) return MatrixFPS22<mint>::get_identity();
    MatrixFPS22<mint> m1 = mat_poly_half_gcd(make_pair(p.first >> K, p.second >> K));
    p = m1 * p;
    if ((int)p.second.size() <= K) return m1;
    naive_gcd(m1, p);
    if ((int)p.second.size() <= K) return m1;
    int j = K * 2 - (int)p.first.size() + 1;
    p.first >>= j, p.second >>= j;
    return mat_poly_half_gcd(p) * m1;
}

template<class mint> MatrixFPS22<mint> mat_poly_gcd(const FPS<mint> &a, const FPS<mint> &b) {
    auto naive_gcd = [](MatrixFPS22<mint> &m, pair<FPS<mint>, FPS<mint>> &p) -> void {
        FPS<mint> q = p.first / p.second, r = p.first - p.second * q;
        FPS<mint> b10 = m.a00 - m.a10 * q, b11 = m.a01 - m.a11 * q;
        swap(b10, m.a10), swap(b11, m.a11), swap(b10, m.a00), swap(b11, m.a01);
        p = {p.second, r};
    };
    pair<FPS<mint>, FPS<mint>> p{a, b};
    p.first.normalize(), p.second.normalize();
    int N = (int)p.first.size(), M = (int)p.second.size();
    if (N < M) {
        MatrixFPS22<mint> mat = mat_poly_gcd(p.second, p.first);
        swap(mat.a00, mat.a01);
        swap(mat.a10, mat.a11);
        return mat;
    }
    MatrixFPS22<mint> res = MatrixFPS22<mint>::get_identity();
    while (true) {
        MatrixFPS22<mint> m1 = mat_poly_half_gcd(p);
        p = m1 * p;
        if (p.second.empty()) return m1 * res;
        naive_gcd(m1, p);
        if (p.second.empty()) return m1 * res;
        res = m1 * res;
    }
}

template<class mint> FPS<mint> poly_gcd(const FPS<mint> &a, const FPS<mint> &b) {
    pair<FPS<mint>, FPS<mint>> p(a, b);
    MatrixFPS22<mint> m = mat_poly_gcd(a, b);
    p = m * p;
    if (!p.first.empty()) {
        mint coef = p.first.back().inv();
        for (auto &x : p.first) x *= coef;
    }
    return p.first;
}

void AOJ_2213() {
    using mint = DynamicModint;
    long long N, P;
    while (cin >> N >> P, N) {
        mint::set_mod(P);
        FPS<mint> a(N+1);
        for (int i = 0; i <= N; i++) {
            long long val;
            cin >> val;
            a[i] = val;
        }
        a.normalize();
        if (a == FPS<mint>()) {
            cout << P << '\n';
            continue;
        }

        FPS<mint> x({0, 1});
        auto xp = mod_pow(x, P, a);
        auto f = xp - x;
        auto g = poly_gcd(f, a);
        cout << (int)g.size() - 1 << '\n';
    }
}


int main() {
    AOJ_2213();
}
accuracy: 1
time_ms: 10
memory_kb: 3712
final_rank: 5

code_snippet: // AOJ #2213
// The Number of Solutions for a Polynomial 2025.2.13

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
 
ll modP;
 
inline ll modAdd(ll a, ll b) {
    a %= modP; b %= modP;
    ll s = a + b;
    s %= modP;
    return s;
}
 
inline ll modSub(ll a, ll b) {
    a %= modP; b %= modP;
    ll s = a - b;
    s %= modP;
    if(s < 0) s += modP;
    return s;
}
 
inline ll modMul(ll a, ll b) {
    a %= modP; b %= modP;
    __int128 t = a;
    t *= b;
    t %= modP;
    return (ll)t;
}
 
ll modPow(ll a, ll b) {
    ll res = 1;
    a %= modP;
    while(b > 0) {
        if(b & 1) res = modMul(res, a);
        a = modMul(a, a);
        b >>= 1;
    }
    return res;
}
 
ll modInv(ll a) {
    return modPow(a, modP - 2);
}
 
typedef vector<ll> Poly;
 
void polyTrim(Poly &a) {
    while(a.size() > 1 && a.back() % modP == 0) a.pop_back();
    if(a.empty()) a.push_back(0);
}
 
Poly polyAdd(const Poly &A, const Poly &B) {
    size_t n = max(A.size(), B.size());
    Poly C(n,0);
    for (int i = 0; i < n; i++){
        ll ca = (i < A.size() ? A[i] : 0);
        ll cb = (i < B.size() ? B[i] : 0);
        C[i] = modAdd(ca, cb);
    }
    polyTrim(C);
    return C;
}
 
Poly polySub(const Poly &A, const Poly &B) {
    size_t n = max(A.size(), B.size());
    Poly C(n,0);
    for (int i = 0; i < n; i++){
        ll ca = (i < A.size() ? A[i] : 0);
        ll cb = (i < B.size() ? B[i] : 0);
        C[i] = modSub(ca, cb);
    }
    polyTrim(C);
    return C;
}
 
Poly polyMulSimple(const Poly &A, const Poly &B) {
    Poly C(A.size() + B.size() - 1, 0);
    for (int i = 0; i < A.size(); i++){
        for (size_t j = 0; j < B.size(); j++){
            C[i+j] = modAdd(C[i+j], modMul(A[i], B[j]));
        }
    }
    polyTrim(C);
    return C;
}
 
pair<Poly, Poly> polyDivMod(Poly A, const Poly &B) {
    polyTrim(A);
    Poly b = B; 
    polyTrim(b);
    Poly Q(max((int)A.size() - (int)b.size() + 1, 0), 0);
    ll invLead = modInv(b.back());
    while(A.size() >= b.size() && !(A.size() == 1 && A[0] == 0)) {
        polyTrim(A);
        int d = A.size() - b.size();
        ll factor = modMul(A.back(), invLead);
        if(Q.size() < d+1) Q.resize(d+1, 0);
        Q[d] = factor;
        for (size_t i = 0; i < b.size(); i++){
            int idx = i + d;
            A[idx] = modSub(A[idx], modMul(factor, b[i]));
        }
        polyTrim(A);
    }
    polyTrim(Q);
    polyTrim(A);
    return {Q, A};
}
 
Poly polyMod(const Poly &A, const Poly &B) {
    auto pr = polyDivMod(A, B);
    return pr.second;
}
 
Poly polyGCD(Poly A, Poly B) {
    polyTrim(A);
    polyTrim(B);
    while(!(B.size() == 1 && B[0] == 0)) {
        Poly r = polyMod(A, B);
        A = B;
        B = r;
    }
    if(!(A.size() == 1 && A[0] == 0)){
        ll invLead = modInv(A.back());
        for(auto &coef : A)
            coef = modMul(coef, invLead);
    }
    polyTrim(A);
    return A;
}
 
Poly polyMulMod(const Poly &A, const Poly &B, const Poly &modPoly) {
    Poly prod = polyMulSimple(A, B);
    Poly rem = polyMod(prod, modPoly);
    return rem;
}
 
Poly polyPow(Poly base, ll exp, const Poly &modPoly) {
    Poly result = {1};
    while(exp > 0){
        if(exp & 1) result = polyMulMod(result, base, modPoly);
        base = polyMulMod(base, base, modPoly);
        exp >>= 1;
    }
    return result;
}
 
 
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
 
    while(true){
        int N;
        cin >> N >> modP;
        if(modP == 0) break;
 
        Poly poly;
        poly.resize(N+1, 0);
        for (int i = 0; i <= N; i++){
            ll coeff;
            cin >> coeff;
            coeff %= modP;
            if(coeff < 0) coeff += modP;
            poly[i] = coeff;
        }
 
        polyTrim(poly);
 
        if(poly.size() == 1 && poly[0] == 0){
            cout << modP << endl;
            continue;
        }
 
        if(poly.size() == 1){
            cout << 0 << endl;
            continue;
        }
 
        {
            ll invLead = modInv(poly.back());
            for (auto &coef : poly)
                coef = modMul(coef, invLead);
            polyTrim(poly);
        }
 
        Poly modPoly = poly;
        Poly Xpoly = {0, 1};
        Poly XtoP = polyPow(Xpoly, modP, modPoly);
        Poly diffPoly = polySub(XtoP, Xpoly);
        Poly g = polyGCD(modPoly, diffPoly);
        int numRoots = (g.size() == 1 && g[0] == 0) ? 0 : (int)g.size() - 1;
        cout << numRoots << endl;
    }
    return 0;
}
accuracy: 1
time_ms: 110
memory_kb: 3440
final_rank: 13

code_snippet: //
// 多項式アルゴリズム (by NTT, FPS)
// 　・係数は p を素数として Fp 体を想定
//
// verified:
//   Yosupo Library Checker - Convolution (Mod 1,000,000,007)
//     https://judge.yosupo.jp/problem/convolution_mod_1000000007
//
//   Yosupo Library Checker - Division of Polynomials
//     https://judge.yosupo.jp/problem/division_of_polynomials
//
//   Yosupo Library Checker - Polynomial Taylor Shift
//     https://judge.yosupo.jp/problem/polynomial_taylor_shift
//
//   AGC 005 F - Many Easy Problems (Polynomial Taylor Shift % mod 924844033)
//     https://atcoder.jp/contests/agc005/tasks/agc005_f
//
//   AOJ 2213 The Number of Solutions for a Polynomial (多項式の割り算 mod Any, 多項式 GCD)
//     http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2213
//


#include <bits/stdc++.h>
using namespace std;


// modint
template<int MOD> struct Fp {
    // inner value
    long long val;
    
    // constructor
    constexpr Fp() : val(0) { }
    constexpr Fp(long long v) : val(v % MOD) {
        if (val < 0) val += MOD;
    }
    constexpr long long get() const { return val; }
    constexpr int get_mod() const { return MOD; }
    
    // arithmetic operators
    constexpr Fp operator + () const { return Fp(*this); }
    constexpr Fp operator - () const { return Fp(0) - Fp(*this); }
    constexpr Fp operator + (const Fp &r) const { return Fp(*this) += r; }
    constexpr Fp operator - (const Fp &r) const { return Fp(*this) -= r; }
    constexpr Fp operator * (const Fp &r) const { return Fp(*this) *= r; }
    constexpr Fp operator / (const Fp &r) const { return Fp(*this) /= r; }
    constexpr Fp& operator += (const Fp &r) {
        val += r.val;
        if (val >= MOD) val -= MOD;
        return *this;
    }
    constexpr Fp& operator -= (const Fp &r) {
        val -= r.val;
        if (val < 0) val += MOD;
        return *this;
    }
    constexpr Fp& operator *= (const Fp &r) {
        val = val * r.val % MOD;
        return *this;
    }
    constexpr Fp& operator /= (const Fp &r) {
        long long a = r.val, b = MOD, u = 1, v = 0;
        while (b) {
            long long t = a / b;
            a -= t * b, swap(a, b);
            u -= t * v, swap(u, v);
        }
        val = val * u % MOD;
        if (val < 0) val += MOD;
        return *this;
    }
    constexpr Fp pow(long long n) const {
        Fp res(1), mul(*this);
        while (n > 0) {
            if (n & 1) res *= mul;
            mul *= mul;
            n >>= 1;
        }
        return res;
    }
    constexpr Fp inv() const {
        Fp res(1), div(*this);
        return res / div;
    }

    // other operators
    constexpr bool operator == (const Fp &r) const {
        return this->val == r.val;
    }
    constexpr bool operator != (const Fp &r) const {
        return this->val != r.val;
    }
    constexpr Fp& operator ++ () {
        ++val;
        if (val >= MOD) val -= MOD;
        return *this;
    }
    constexpr Fp& operator -- () {
        if (val == 0) val += MOD;
        --val;
        return *this;
    }
    constexpr Fp operator ++ (int) const {
        Fp res = *this;
        ++*this;
        return res;
    }
    constexpr Fp operator -- (int) const {
        Fp res = *this;
        --*this;
        return res;
    }
    friend constexpr istream& operator >> (istream &is, Fp<MOD> &x) {
        is >> x.val;
        x.val %= MOD;
        if (x.val < 0) x.val += MOD;
        return is;
    }
    friend constexpr ostream& operator << (ostream &os, const Fp<MOD> &x) {
        return os << x.val;
    }
    friend constexpr Fp<MOD> pow(const Fp<MOD> &r, long long n) {
        return r.pow(n);
    }
    friend constexpr Fp<MOD> inv(const Fp<MOD> &r) {
        return r.inv();
    }
};

namespace NTT {
    long long modpow(long long a, long long n, int mod) {
        long long res = 1;
        while (n > 0) {
            if (n & 1) res = res * a % mod;
            a = a * a % mod;
            n >>= 1;
        }
        return res;
    }

    long long modinv(long long a, int mod) {
        long long b = mod, u = 1, v = 0;
        while (b) {
            long long t = a / b;
            a -= t * b, swap(a, b);
            u -= t * v, swap(u, v);
        }
        u %= mod;
        if (u < 0) u += mod;
        return u;
    }

    int calc_primitive_root(int mod) {
        if (mod == 2) return 1;
        if (mod == 167772161) return 3;
        if (mod == 469762049) return 3;
        if (mod == 754974721) return 11;
        if (mod == 998244353) return 3;
        int divs[20] = {};
        divs[0] = 2;
        int cnt = 1;
        long long x = (mod - 1) / 2;
        while (x % 2 == 0) x /= 2;
        for (long long i = 3; i * i <= x; i += 2) {
            if (x % i == 0) {
                divs[cnt++] = i;
                while (x % i == 0) x /= i;
            }
        }
        if (x > 1) divs[cnt++] = x;
        for (int g = 2;; g++) {
            bool ok = true;
            for (int i = 0; i < cnt; i++) {
                if (modpow(g, (mod - 1) / divs[i], mod) == 1) {
                    ok = false;
                    break;
                }
            }
            if (ok) return g;
        }
    }

    int get_fft_size(int N, int M) {
        int size_a = 1, size_b = 1;
        while (size_a < N) size_a <<= 1;
        while (size_b < M) size_b <<= 1;
        return max(size_a, size_b) << 1;
    }

    // number-theoretic transform
    template<class mint> void trans(vector<mint> &v, bool inv = false) {
        if (v.empty()) return;
        int N = (int)v.size();
        int MOD = v[0].get_mod();
        int PR = calc_primitive_root(MOD);
        static bool first = true;
        static vector<long long> vbw(30), vibw(30);
        if (first) {
            first = false;
            for (int k = 0; k < 30; ++k) {
                vbw[k] = modpow(PR, (MOD - 1) >> (k + 1), MOD);
                vibw[k] = modinv(vbw[k], MOD);
            }
        }
        for (int i = 0, j = 1; j < N - 1; j++) {
            for (int k = N >> 1; k > (i ^= k); k >>= 1);
            if (i > j) swap(v[i], v[j]);
        }
        for (int k = 0, t = 2; t <= N; ++k, t <<= 1) {
            long long bw = vbw[k];
            if (inv) bw = vibw[k];
            for (int i = 0; i < N; i += t) {
                mint w = 1;
                for (int j = 0; j < t/2; ++j) {
                    int j1 = i + j, j2 = i + j + t/2;
                    mint c1 = v[j1], c2 = v[j2] * w;
                    v[j1] = c1 + c2;
                    v[j2] = c1 - c2;
                    w *= bw;
                }
            }
        }
        if (inv) {
            long long invN = modinv(N, MOD);
            for (int i = 0; i < N; ++i) v[i] = v[i] * invN;
        }
    }

    // for garner
    static constexpr int MOD0 = 754974721;
    static constexpr int MOD1 = 167772161;
    static constexpr int MOD2 = 469762049;
    using mint0 = Fp<MOD0>;
    using mint1 = Fp<MOD1>;
    using mint2 = Fp<MOD2>;
    static const mint1 imod0 = 95869806; // modinv(MOD0, MOD1);
    static const mint2 imod1 = 104391568; // modinv(MOD1, MOD2);
    static const mint2 imod01 = 187290749; // imod1 / MOD0;

    // small case (T = mint, long long)
    template<class T> vector<T> naive_mul(const vector<T> &A, const vector<T> &B) {
        if (A.empty() || B.empty()) return {};
        int N = (int)A.size(), M = (int)B.size();
        vector<T> res(N + M - 1);
        for (int i = 0; i < N; ++i)
            for (int j = 0; j < M; ++j)
                res[i + j] += A[i] * B[j];
        return res;
    }

    // mint
    template<class mint> vector<mint> mul(const vector<mint> &A, const vector<mint> &B) {
        if (A.empty() || B.empty()) return {};
        int N = (int)A.size(), M = (int)B.size();
        if (min(N, M) < 30) return naive_mul(A, B);
        int MOD = A[0].get_mod();
        int size_fft = get_fft_size(N, M);
        if (MOD == 998244353) {
            vector<mint> a(size_fft), b(size_fft), c(size_fft);
            for (int i = 0; i < N; ++i) a[i] = A[i];
            for (int i = 0; i < M; ++i) b[i] = B[i];
            trans(a), trans(b);
            vector<mint> res(size_fft);
            for (int i = 0; i < size_fft; ++i) res[i] = a[i] * b[i];
            trans(res, true);
            res.resize(N + M - 1);
            return res;
        }
        vector<mint0> a0(size_fft, 0), b0(size_fft, 0), c0(size_fft, 0);
        vector<mint1> a1(size_fft, 0), b1(size_fft, 0), c1(size_fft, 0);
        vector<mint2> a2(size_fft, 0), b2(size_fft, 0), c2(size_fft, 0);
        for (int i = 0; i < N; ++i)
            a0[i] = A[i].val, a1[i] = A[i].val, a2[i] = A[i].val;
        for (int i = 0; i < M; ++i)
            b0[i] = B[i].val, b1[i] = B[i].val, b2[i] = B[i].val;
        trans(a0), trans(a1), trans(a2), trans(b0), trans(b1), trans(b2);
        for (int i = 0; i < size_fft; ++i) {
            c0[i] = a0[i] * b0[i];
            c1[i] = a1[i] * b1[i];
            c2[i] = a2[i] * b2[i];
        }
        trans(c0, true), trans(c1, true), trans(c2, true);
        mint mod0 = MOD0, mod01 = mod0 * MOD1;
        vector<mint> res(N + M - 1);
        for (int i = 0; i < N + M - 1; ++i) {
            int y0 = c0[i].val;
            int y1 = (imod0 * (c1[i] - y0)).val;
            int y2 = (imod01 * (c2[i] - y0) - imod1 * y1).val;
            res[i] = mod01 * y2 + mod0 * y1 + y0;
        }
        return res;
    }
};

// Polynomial
template<typename mint> struct Poly : vector<mint> {
    using vector<mint>::vector;
 
    // constructor
    constexpr Poly(const vector<mint> &r) : vector<mint>(r) {}
 
    // core operator
    constexpr mint eval(const mint &v) {
        mint res = 0;
        for (int i = (int)this->size()-1; i >= 0; --i) {
            res *= v;
            res += (*this)[i];
        }
        return res;
    }
    constexpr Poly& normalize() {
        while (!this->empty() && this->back() == 0) this->pop_back();
        return *this;
    }
 
    // basic operator
    constexpr Poly operator - () const noexcept {
        Poly res = (*this);
        for (int i = 0; i < (int)res.size(); ++i) res[i] = -res[i];
        return res;
    }
    constexpr Poly operator + (const mint &v) const { return Poly(*this) += v; }
    constexpr Poly operator + (const Poly &r) const { return Poly(*this) += r; }
    constexpr Poly operator - (const mint &v) const { return Poly(*this) -= v; }
    constexpr Poly operator - (const Poly &r) const { return Poly(*this) -= r; }
    constexpr Poly operator * (const mint &v) const { return Poly(*this) *= v; }
    constexpr Poly operator * (const Poly &r) const { return Poly(*this) *= r; }
    constexpr Poly operator / (const mint &v) const { return Poly(*this) /= v; }
    constexpr Poly operator / (const Poly &r) const { return Poly(*this) /= r; }
    constexpr Poly operator % (const Poly &r) const { return Poly(*this) %= r; }
    constexpr Poly operator << (int x) const { return Poly(*this) <<= x; }
    constexpr Poly operator >> (int x) const { return Poly(*this) >>= x; }
    constexpr Poly& operator += (const mint &v) {
        if (this->empty()) this->resize(1);
        (*this)[0] += v;
        return *this;
    }
    constexpr Poly& operator += (const Poly &r) {
        if (r.size() > this->size()) this->resize(r.size());
        for (int i = 0; i < (int)r.size(); ++i) (*this)[i] += r[i];
        return this->normalize();
    }
    constexpr Poly& operator -= (const mint &v) {
        if (this->empty()) this->resize(1);
        (*this)[0] -= v;
        return *this;
    }
    constexpr Poly& operator -= (const Poly &r) {
        if (r.size() > this->size()) this->resize(r.size());
        for (int i = 0; i < (int)r.size(); ++i) (*this)[i] -= r[i];
        return this->normalize();
    }
    constexpr Poly& operator *= (const mint &v) {
        for (int i = 0; i < (int)this->size(); ++i) (*this)[i] *= v;
        return *this;
    }
    constexpr Poly& operator *= (const Poly &r) {
        return *this = NTT::mul((*this), r);
    }
    constexpr Poly& operator <<= (int x) {
        Poly res(x, 0);
        res.insert(res.end(), begin(*this), end(*this));
        return *this = res;
    }
    constexpr Poly& operator >>= (int x) {
        Poly res;
        res.insert(res.end(), begin(*this) + x, end(*this));
        return *this = res;
    }
    
    // division, pow
    constexpr Poly& operator /= (const mint &v) {
        assert(v != 0);
        mint iv = modinv(v);
        for (int i = 0; i < (int)this->size(); ++i) (*this)[i] *= iv;
        return *this;
    }
    constexpr Poly& operator /= (const Poly &r) {
        assert(!r.empty());
        assert(r.back() != 0);
        this->normalize();
        if (this->size() < r.size()) {
            this->clear();
            return *this;
        }
        int need = (int)this->size() - (int)r.size() + 1;
        *this = (rev().pre(need) * r.rev().inner_inv(need)).pre(need).rev();
        return *this;
    }
    constexpr Poly& operator %= (const Poly &r) {
        assert(!r.empty());
        assert(r.back() != 0);
        this->normalize();
        Poly q = (*this) / r;
        return *this -= q * r;
    }
    
    // FPS functions
    constexpr Poly pre(int siz) const {
        return Poly(begin(*this), begin(*this) + min((int)this->size(), siz));
    }
    constexpr Poly rev() const {
        Poly res = *this;
        reverse(begin(res), end(res));
        return res;
    }
    
    // df/dx
    constexpr Poly diff() const {
        int n = (int)this->size();
        Poly res(n-1);
        for (int i = 1; i < n; ++i) res[i-1] = (*this)[i] * i;
        return res;
    }
    
    // \int f dx
    constexpr Poly integral() const {
        int n = (int)this->size();
        Poly res(n+1, 0);
        for (int i = 0; i < n; ++i) res[i+1] = (*this)[i] / (i+1);
        return res;
    }

    // inv(f), f[0] must not be 0
    constexpr Poly inner_inv(int deg) const {
        assert((*this)[0] != 0);
        if (deg < 0) deg = (int)this->size();
        Poly res({mint(1) / (*this)[0]});
        for (int i = 1; i < deg; i <<= 1) {
            res = (res + res - res * res * pre(i << 1)).pre(i << 1);
        }
        res.resize(deg);
        return res;
    }
    constexpr Poly inner_inv() const {
        return inner_inv((int)this->size());
    }
    
    // log(f) = \int f'/f dx, f[0] must be 1
    constexpr Poly inner_log(int deg) const {
        assert((*this)[0] == 1);
        Poly res = (diff() * inner_inv(deg)).integral();
        res.resize(deg);
        return res;
    }
    constexpr Poly inner_log() const {
        return inner_log((int)this->size());
    }
    
    // exp(f), f[0] must be 0
    constexpr Poly inner_exp(int deg) const {
        assert((*this)[0] == 0);
        Poly res(1, 1);
        for (int i = 1; i < deg; i <<= 1) {
            res = res * (pre(i << 1) - res.inner_log(i << 1) + 1).pre(i << 1);
        }
        res.resize(deg);
        return res;
    }
    constexpr Poly inner_exp() const {
        return inner_exp((int)this->size());
    }
    
    // pow(f) = exp(e * log f)
    constexpr Poly inner_pow(long long e, int deg) const {
        if (e == 0) {
            Poly res(deg, 0);
            res[0] = 1;
            return res;
        }
        long long i = 0;
        while (i < (int)this->size() && (*this)[i] == 0) ++i;
        if (i == (int)this->size() || i > (deg - 1) / e) return Poly(deg, 0);
        mint k = (*this)[i];
        Poly res = ((((*this) >> i) / k).inner_log(deg) * e).inner_exp(deg)
                    * mint(k).inner_pow(e) << (e * i);
        res.resize(deg);
        return res;
    }
    constexpr Poly inner_pow(long long e) const {
        return inner_pow(e, (int)this->size());
    }
};


/*/////////////////////////////*/
// Polynomial Algorithms
/*/////////////////////////////*/

// Binomial coefficient
template<class T> struct BiCoef {
    vector<T> fact_, inv_, finv_;
    constexpr BiCoef() {}
    constexpr BiCoef(int n) : fact_(n, 1), inv_(n, 1), finv_(n, 1) {
        init(n);
    }
    constexpr void init(int n) {
        fact_.assign(n, 1), inv_.assign(n, 1), finv_.assign(n, 1);
        int MOD = fact_[0].get_mod();
        for(int i = 2; i < n; i++){
            fact_[i] = fact_[i-1] * i;
            inv_[i] = -inv_[MOD%i] * (MOD/i);
            finv_[i] = finv_[i-1] * inv_[i];
        }
    }
    constexpr T com(int n, int k) const {
        if (n < k || n < 0 || k < 0) return 0;
        return fact_[n] * finv_[k] * finv_[n-k];
    }
    constexpr T fact(int n) const {
        if (n < 0) return 0;
        return fact_[n];
    }
    constexpr T inv(int n) const {
        if (n < 0) return 0;
        return inv_[n];
    }
    constexpr T finv(int n) const {
        if (n < 0) return 0;
        return finv_[n];
    }
};

// Polynomial Taylor Shift
// given: f(x), c
// find: coefficients of f(x + c)
template<class mint> Poly<mint> PolynomialTaylorShift(const Poly<mint> &f, long long c) {
    int N = (int)f.size() - 1;
    BiCoef<mint> bc(N + 1);
    
    // convolution
    Poly<mint> p(N + 1), q(N + 1);
    for (int i = 0; i <= N; ++i) {
        p[i] = f[i] * bc.fact(i);
        q[N - i] = mint(c).pow(i) * bc.finv(i);
    }
    Poly<mint> pq = p * q;
    
    // result
    Poly<mint> res(N + 1);
    for (int i = 0; i <= N; ++i) res[i] = pq[i + N] * bc.finv(i);
    return res;
}


/*/////////////////////////////*/
// for any mod
/*/////////////////////////////*/

// dynamic modint
struct DynamicModint {
    using mint = DynamicModint;
    
    // static menber
    static int MOD;
    
    // inner value
    long long val;
    
    // constructor
    DynamicModint() : val(0) { }
    DynamicModint(long long v) : val(v % MOD) {
        if (val < 0) val += MOD;
    }
    long long get() const { return val; }
    static int get_mod() { return MOD; }
    static void set_mod(int mod) { MOD = mod; }
    
    // arithmetic operators
    mint operator + () const { return mint(*this); }
    mint operator - () const { return mint(0) - mint(*this); }
    mint operator + (const mint &r) const { return mint(*this) += r; }
    mint operator - (const mint &r) const { return mint(*this) -= r; }
    mint operator * (const mint &r) const { return mint(*this) *= r; }
    mint operator / (const mint &r) const { return mint(*this) /= r; }
    mint& operator += (const mint &r) {
        val += r.val;
        if (val >= MOD) val -= MOD;
        return *this;
    }
    mint& operator -= (const mint &r) {
        val -= r.val;
        if (val < 0) val += MOD;
        return *this;
    }
    mint& operator *= (const mint &r) {
        val = val * r.val % MOD;
        return *this;
    }
    mint& operator /= (const mint &r) {
        long long a = r.val, b = MOD, u = 1, v = 0;
        while (b) {
            long long t = a / b;
            a -= t * b, swap(a, b);
            u -= t * v, swap(u, v);
        }
        val = val * u % MOD;
        if (val < 0) val += MOD;
        return *this;
    }
    mint pow(long long n) const {
        mint res(1), mul(*this);
        while (n > 0) {
            if (n & 1) res *= mul;
            mul *= mul;
            n >>= 1;
        }
        return res;
    }
    mint inv() const {
        mint res(1), div(*this);
        return res / div;
    }

    // other operators
    bool operator == (const mint &r) const {
        return this->val == r.val;
    }
    bool operator != (const mint &r) const {
        return this->val != r.val;
    }
    mint& operator ++ () {
        ++val;
        if (val >= MOD) val -= MOD;
        return *this;
    }
    mint& operator -- () {
        if (val == 0) val += MOD;
        --val;
        return *this;
    }
    mint operator ++ (int) {
        mint res = *this;
        ++*this;
        return res;
    }
    mint operator -- (int) {
        mint res = *this;
        --*this;
        return res;
    }
    friend istream& operator >> (istream &is, mint &x) {
        is >> x.val;
        x.val %= x.get_mod();
        if (x.val < 0) x.val += x.get_mod();
        return is;
    }
    friend ostream& operator << (ostream &os, const mint &x) {
        return os << x.val;
    }
    friend mint pow(const mint &r, long long n) {
        return r.pow(n);
    }
    friend mint inv(const mint &r) {
        return r.inv();
    }
};

int DynamicModint::MOD;



/*/////////////////////////////*/
// Examples
/*/////////////////////////////*/

void Yosupo_Convolution_mod_1000000007() {
    const int MOD = 1000000007;
    using mint = Fp<MOD>;
    
    int N, M;
    cin >> N >> M;
    Poly<mint> a(N), b(M);
    for (int i = 0; i < N; ++i) cin >> a[i];
    for (int i = 0; i < M; ++i) cin >> b[i];
    Poly<mint> res = a * b;
    for (auto v : res) cout << v << " ";
    cout << endl;
}

void Yosupo_Division_of_Polynomials() {
    const int MOD = 998244353;
    using mint = Fp<MOD>;
    
    int N, M;
    cin >> N >> M;
    Poly<mint> f(N), g(M);
    for (int i = 0; i < N; ++i) cin >> f[i];
    for (int i = 0; i < M; ++i) cin >> g[i];
    
    Poly<mint> q = f / g, r = f - g * q;
    cout << q.size() << " " << r.size() << endl;
    for (auto v : q) cout << v << " ";
    cout << endl;
    for (auto v : r) cout << v << " ";
    cout << endl;
}

void Yosupo_Polynomial_Taylor_Shift() {
    const int MOD = 998244353;
    using mint = Fp<MOD>;
    
    long long N, c;
    cin >> N >> c;
    Poly<mint> a(N);
    for (int i = 0; i < N; ++i) cin >> a[i];
    
    Poly<mint> res = PolynomialTaylorShift(a, c);
    for (int i = 0; i < N; ++i) cout << res[i] << " ";
    cout << endl;
}

// AGC 005 F
void AGC_005_F() {
    const int MOD = 924844033;
    using mint = Fp<MOD>;
    
    int N;
    cin >> N;
    BiCoef<mint> bc(N + 1);
    vector<vector<int>> G(N);
    for (int i = 0; i < N-1; ++i) {
        int a, b;
        cin >> a >> b;
        --a, --b;
        G[a].push_back(b);
        G[b].push_back(a);
    }
    
    Poly<mint> f(N+1, 0);
    vector<int> si(N, 1);
    auto rec = [&](auto self, int v, int p = -1) -> void {
        for (auto ch : G[v]) {
            if (ch == p) continue;
            self(self, ch, v);
            ++f[si[ch]];
            si[v] += si[ch];
        }
        ++f[N - si[v]];
    };
    rec(rec, 0);
    
    Poly<mint> g = PolynomialTaylorShift(f, 1);
    for (int k = 1; k <= N; ++k) cout << bc.com(N, k) * N - g[k] << endl;
}


#define REP(i, n) for (long long i = 0; i < (long long)(n); ++i)
#define REP2(i, a, b) for (long long i = a; i < (long long)(b); ++i)
#define COUT(x) cout << #x << " = " << (x) << " (L" << __LINE__ << ")" << endl
template<class T1, class T2> ostream& operator << (ostream &s, pair<T1,T2> P)
{ return s << '<' << P.first << ", " << P.second << '>'; }
template<class T> ostream& operator << (ostream &s, vector<T> P)
{ for (int i = 0; i < P.size(); ++i) { if (i > 0) { s << " "; } s << P[i]; } return s; }
template<class T> ostream& operator << (ostream &s, deque<T> P)
{ for (int i = 0; i < P.size(); ++i) { if (i > 0) { s << " "; } s << P[i]; } return s; }
template<class T> ostream& operator << (ostream &s, vector<vector<T> > P)
{ for (int i = 0; i < P.size(); ++i) { s << endl << P[i]; } return s << endl; }
template<class T> ostream& operator << (ostream &s, set<T> P)
{ for(auto it : P) { s << "<" << it << "> "; } return s; }
template<class T> ostream& operator << (ostream &s, multiset<T> P)
{ for(auto it : P) { s << "<" << it << "> "; } return s; }
template<class T1, class T2> ostream& operator << (ostream &s, map<T1,T2> P)
{ for(auto it : P) { s << "<" << it.first << "->" << it.second << "> "; } return s; }



// AOJ 2213
void AOJ_2213() {
    using mint = DynamicModint;
    
    auto pow = [&](const Poly<mint> &f, long long n, const Poly<mint> &m) -> Poly<mint> {
        Poly<mint> res = {1}, mul = f;
        while (n > 0) {
            if (n & 1) res = res * mul % m;
            mul = mul * mul % m;
            n >>= 1;
        }
        return res;
    };
    auto gcd = [&](auto self, const Poly<mint> &a, const Poly<mint> &b) -> Poly<mint> {
        if (b.empty()) return a;
        else return self(self, b, a % b);
    };
    
    long long N, P;
    while (cin >> N >> P) {
        if (N == 0) break;
        mint::set_mod(P);
        
        Poly<mint> f(N+1);
        for (int i = 0; i < N+1; ++i) cin >> f[i];
        f.normalize();
        if (f.empty()) {
            cout << P << endl;
            continue;
        }
        Poly<mint> x = {0, 1};
        Poly<mint> g = pow(x, P, f) - x;
        Poly<mint> res = gcd(gcd, f, g);
        cout << (int)res.size() - 1 << endl;
    }
}


int main() {
    //Yosupo_Convolution_mod_1000000007();
    //Yosupo_Division_of_Polynomials();
    //Yosupo_Polynomial_Taylor_Shift();
    //AGC_005_F();
    AOJ_2213();
}
accuracy: 1
time_ms: 40
memory_kb: 3508
final_rank: 7

code_snippet: //
// Formal Power Series (on runtime mod)
//
// verified:
//   Yosupo Judge
//     https://judge.yosupo.jp/problem/inv_of_formal_power_series
//
//   AOJ 2213 The Number of Solutions for a Polynomial
//     http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2213
//


#include <bits/stdc++.h>
using namespace std;

#define COUT(x) cout << #x << " = " << (x) << " (L" << __LINE__ << ")" << endl
template<class T1, class T2> ostream& operator << (ostream &s, pair<T1,T2> P)
{ return s << '<' << P.first << ", " << P.second << '>'; }
template<class T> ostream& operator << (ostream &s, vector<T> P)
{ for (int i = 0; i < P.size(); ++i) { if (i > 0) { s << " "; } s << P[i]; } return s; }
template<class T> ostream& operator << (ostream &s, vector<vector<T> > P)
{ for (int i = 0; i < P.size(); ++i) { s << endl << P[i]; } return s << endl; }
template<class T> ostream& operator << (ostream &s, set<T> P)
{ for(auto it : P) { s << "<" << it << "> "; } return s << endl; }
template<class T1, class T2> ostream& operator << (ostream &s, map<T1,T2> P)
{ for(auto it : P) { s << "<" << it.first << "->" << it.second << "> "; } return s << endl; }


// modint (replace MODS[0] on runtime)
vector<int> MODS = { 1000000007, 754974721, 167772161, 469762049 };
template<int IND = 0> struct Fp {
    long long val;
    constexpr Fp(long long v = 0) noexcept : val(v % MODS[IND]) {
        if (val < 0) val += MODS[IND];
    }
    constexpr int getmod() const { return MODS[IND]; }
    constexpr Fp operator - () const noexcept {
        return val ? MODS[IND] - val : 0;
    }
    constexpr Fp operator + (const Fp& r) const noexcept { return Fp(*this) += r; }
    constexpr Fp operator - (const Fp& r) const noexcept { return Fp(*this) -= r; }
    constexpr Fp operator * (const Fp& r) const noexcept { return Fp(*this) *= r; }
    constexpr Fp operator / (const Fp& r) const noexcept { return Fp(*this) /= r; }
    constexpr Fp& operator += (const Fp& r) noexcept {
        val += r.val;
        if (val >= MODS[IND]) val -= MODS[IND];
        return *this;
    }
    constexpr Fp& operator -= (const Fp& r) noexcept {
        val -= r.val;
        if (val < 0) val += MODS[IND];
        return *this;
    }
    constexpr Fp& operator *= (const Fp& r) noexcept {
        val = val * r.val % MODS[IND];
        return *this;
    }
    constexpr Fp& operator /= (const Fp& r) noexcept {
        long long a = r.val, b = MODS[IND], u = 1, v = 0;
        while (b) {
            long long t = a / b;
            a -= t * b; swap(a, b);
            u -= t * v; swap(u, v);
        }
        val = val * u % MODS[IND];
        if (val < 0) val += MODS[IND];
        return *this;
    }
    constexpr bool operator == (const Fp& r) const noexcept {
        return this->val == r.val;
    }
    constexpr bool operator != (const Fp& r) const noexcept {
        return this->val != r.val;
    }
    friend constexpr istream& operator >> (istream& is, Fp<IND>& x) noexcept {
        is >> x.val;
        x.val %= MODS[IND];
        if (x.val < 0) x.val += MODS[IND];
        return is;
    }
    friend constexpr ostream& operator << (ostream& os, const Fp<IND>& x) noexcept {
        return os << x.val;
    }
    friend constexpr Fp<IND> modpow(const Fp<IND>& r, long long n) noexcept {
        if (n == 0) return 1;
        auto t = modpow(r, n / 2);
        t = t * t;
        if (n & 1) t = t * r;
        return t;
    }
    friend constexpr Fp<IND> modinv(const Fp<IND>& r) noexcept {
        long long a = r.val, b = MODS[IND], u = 1, v = 0;
        while (b) {
            long long t = a / b;
            a -= t * b, swap(a, b);
            u -= t * v, swap(u, v);
        }
        return Fp<IND>(u);
    }
};

namespace NTT {    
    long long modpow(long long a, long long n, int mod) {
        long long res = 1;
        while (n > 0) {
            if (n & 1) res = res * a % mod;
            a = a * a % mod;
            n >>= 1;
        }
        return res;
    }

    long long modinv(long long a, int mod) {
        long long b = mod, u = 1, v = 0;
        while (b) {
            long long t = a / b;
            a -= t * b, swap(a, b);
            u -= t * v, swap(u, v);
        }
        u %= mod;
        if (u < 0) u += mod;
        return u;
    }

    int calc_primitive_root(int mod) {
        if (mod == 2) return 1;
        if (mod == 167772161) return 3;
        if (mod == 469762049) return 3;
        if (mod == 754974721) return 11;
        if (mod == 998244353) return 3;
        int divs[20] = {};
        divs[0] = 2;
        int cnt = 1;
        long long x = (mod - 1) / 2;
        while (x % 2 == 0) x /= 2;
        for (long long i = 3; i * i <= x; i += 2) {
            if (x % i == 0) {
                divs[cnt++] = i;
                while (x % i == 0) x /= i;
            }
        }
        if (x > 1) divs[cnt++] = x;
        for (int g = 2;; g++) {
            bool ok = true;
            for (int i = 0; i < cnt; i++) {
                if (modpow(g, (mod - 1) / divs[i], mod) == 1) {
                    ok = false;
                    break;
                }
            }
            if (ok) return g;
        }
    }

    int get_fft_size(int N, int M) {
        int size_a = 1, size_b = 1;
        while (size_a < N) size_a <<= 1;
        while (size_b < M) size_b <<= 1;
        return max(size_a, size_b) << 1;
    }

    // number-theoretic transform
    set<int> setmod;
    template<class mint> void trans(vector<mint>& v, bool inv = false) {
        if (v.empty()) return;
        int N = (int)v.size();
        int MOD = v[0].getmod();
        int PR = calc_primitive_root(MOD);
        static vector<long long> vbw(30), vibw(30);
        if (!setmod.count(MOD)) {
            setmod.insert(MOD);
            for (int k = 0; k < 30; ++k) {
                vbw[k] = modpow(PR, (MOD - 1) >> (k + 1), MOD);
                vibw[k] = modinv(vbw[k], MOD);
            }
        }
        for (int i = 0, j = 1; j < N - 1; j++) {
            for (int k = N >> 1; k > (i ^= k); k >>= 1);
            if (i > j) swap(v[i], v[j]);
        }
        for (int k = 0, t = 2; t <= N; ++k, t <<= 1) {
            long long bw = vbw[k];
            if (inv) bw = vibw[k];
            for (int i = 0; i < N; i += t) {
                mint w = 1;
                for (int j = 0; j < t/2; ++j) {
                    int j1 = i + j, j2 = i + j + t/2;
                    mint c1 = v[j1], c2 = v[j2] * w;
                    v[j1] = c1 + c2;
                    v[j2] = c1 - c2;
                    w *= bw;
                }
            }
        }
        if (inv) {
            long long invN = modinv(N, MOD);
            for (int i = 0; i < N; ++i) v[i] = v[i] * invN;
        }
    }

    // for garner
    static constexpr int IND1 = 1; //754974721;
    static constexpr int IND2 = 2; //167772161;
    static constexpr int IND3 = 3; //469762049;
    using mint1 = Fp<IND1>;
    using mint2 = Fp<IND2>;
    using mint3 = Fp<IND3>;
    static const mint2 imod1 = 95869806; // modinv(MOD1, MOD2);
    static const mint3 imod2 = 104391568; // modinv(MOD2, MOD3);
    static const mint3 imod12 = 187290749; // imod2 / MOD1;

    // small case (T = mint, long long)
    template<class T> vector<T> naive_mul 
    (const vector<T>& A, const vector<T>& B) {
        if (A.empty() || B.empty()) return {};
        int N = (int)A.size(), M = (int)B.size();
        vector<T> res(N + M - 1);
        for (int i = 0; i < N; ++i)
            for (int j = 0; j < M; ++j)
                res[i + j] += A[i] * B[j];
        return res;
    }

    // mint
    template<class mint> vector<mint> mul
    (const vector<mint>& A, const vector<mint>& B) {
        if (A.empty() || B.empty()) return {};
        int N = (int)A.size(), M = (int)B.size();
        if (min(N, M) < 80) return naive_mul(A, B);
        int MOD = A[0].getmod();
        int size_fft = get_fft_size(N, M);
        if (MOD == 998244353) {
            vector<mint> a(size_fft), b(size_fft), c(size_fft);
            for (int i = 0; i < N; ++i) a[i] = A[i];
            for (int i = 0; i < M; ++i) b[i] = B[i];
            trans(a), trans(b);
            vector<mint> res(size_fft);
            for (int i = 0; i < size_fft; ++i) res[i] = a[i] * b[i];
            trans(res, true);
            res.resize(N + M - 1);
            return res;
        }
        vector<mint1> a1(size_fft, 0), b1(size_fft, 0), c1(size_fft, 0);
        vector<mint2> a2(size_fft, 0), b2(size_fft, 0), c2(size_fft, 0);
        vector<mint3> a3(size_fft, 0), b3(size_fft, 0), c3(size_fft, 0);
        for (int i = 0; i < N; ++i)
            a1[i] = A[i].val, a2[i] = A[i].val, a3[i] = A[i].val;
        for (int i = 0; i < M; ++i)
            b1[i] = B[i].val, b2[i] = B[i].val, b3[i] = B[i].val;
        trans(a1), trans(a2), trans(a3), trans(b1), trans(b2), trans(b3);
        for (int i = 0; i < size_fft; ++i) {
            c1[i] = a1[i] * b1[i];
            c2[i] = a2[i] * b2[i];
            c3[i] = a3[i] * b3[i];
        }
        trans(c1, true), trans(c2, true), trans(c3, true);
        mint mod1 = MODS[IND1], mod12 = mod1 * MODS[IND2];
        vector<mint> res(N + M - 1);
        for (int i = 0; i < N + M - 1; ++i) {
            int y1 = c1[i].val;
            int y2 = (imod1 * (c2[i] - y1)).val;
            int y3 = (imod12 * (c3[i] - y1) - imod2 * y2).val;
            res[i] = mod12 * y3 + mod1 * y2 + y1;
        }
        return res;
    }
};

// Binomial Coefficient
template<class T> struct BiCoef {
    vector<T> fact_, inv_, finv_;
    constexpr BiCoef() {}
    constexpr BiCoef(int n) noexcept : fact_(n, 1), inv_(n, 1), finv_(n, 1) {
        init(n);
    }
    constexpr void init(int n) noexcept {
        fact_.assign(n, 1), inv_.assign(n, 1), finv_.assign(n, 1);
        int MOD = fact_[0].getmod();
        for(int i = 2; i < n; i++){
            fact_[i] = fact_[i-1] * i;
            inv_[i] = -inv_[MOD%i] * (MOD/i);
            finv_[i] = finv_[i-1] * inv_[i];
        }
    }
    constexpr T com(int n, int k) const noexcept {
        if (n < k || n < 0 || k < 0) return 0;
        return fact_[n] * finv_[k] * finv_[n-k];
    }
    constexpr T fact(int n) const noexcept {
        if (n < 0) return 0;
        return fact_[n];
    }
    constexpr T inv(int n) const noexcept {
        if (n < 0) return 0;
        return inv_[n];
    }
    constexpr T finv(int n) const noexcept {
        if (n < 0) return 0;
        return finv_[n];
    }
};

// Formal Power Series
template <typename mint> struct FPS : vector<mint> {
    using vector<mint>::vector;
 
    // constructor
    FPS(const vector<mint>& r) : vector<mint>(r) {}
 
    // core operator
    inline FPS pre(int siz) const {
        return FPS(begin(*this), begin(*this) + min((int)this->size(), siz));
    }
    inline FPS rev() const {
        FPS res = *this;
        reverse(begin(res), end(res));
        return res;
    }
    inline FPS& normalize() {
        while (!this->empty() && this->back() == 0) this->pop_back();
        return *this;
    }
 
    // basic operator
    inline FPS operator - () const noexcept {
        FPS res = (*this);
        for (int i = 0; i < (int)res.size(); ++i) res[i] = -res[i];
        return res;
    }
    inline FPS operator + (const mint& v) const { return FPS(*this) += v; }
    inline FPS operator + (const FPS& r) const { return FPS(*this) += r; }
    inline FPS operator - (const mint& v) const { return FPS(*this) -= v; }
    inline FPS operator - (const FPS& r) const { return FPS(*this) -= r; }
    inline FPS operator * (const mint& v) const { return FPS(*this) *= v; }
    inline FPS operator * (const FPS& r) const { return FPS(*this) *= r; }
    inline FPS operator / (const mint& v) const { return FPS(*this) /= v; }
    inline FPS operator << (int x) const { return FPS(*this) <<= x; }
    inline FPS operator >> (int x) const { return FPS(*this) >>= x; }
    inline FPS& operator += (const mint& v) {
        if (this->empty()) this->resize(1);
        (*this)[0] += v;
        return *this;
    }
    inline FPS& operator += (const FPS& r) {
        if (r.size() > this->size()) this->resize(r.size());
        for (int i = 0; i < (int)r.size(); ++i) (*this)[i] += r[i];
        return this->normalize();
    }
    inline FPS& operator -= (const mint& v) {
        if (this->empty()) this->resize(1);
        (*this)[0] -= v;
        return *this;
    }
    inline FPS& operator -= (const FPS& r) {
        if (r.size() > this->size()) this->resize(r.size());
        for (int i = 0; i < (int)r.size(); ++i) (*this)[i] -= r[i];
        return this->normalize();
    }
    inline FPS& operator *= (const mint& v) {
        for (int i = 0; i < (int)this->size(); ++i) (*this)[i] *= v;
        return *this;
    }
    inline FPS& operator *= (const FPS& r) {
        return *this = NTT::mul((*this), r);
    }
    inline FPS& operator /= (const mint& v) {
        assert(v != 0);
        mint iv = modinv(v);
        for (int i = 0; i < (int)this->size(); ++i) (*this)[i] *= iv;
        return *this;
    }
    inline FPS& operator <<= (int x) {
        FPS res(x, 0);
        res.insert(res.end(), begin(*this), end(*this));
        return *this = res;
    }
    inline FPS& operator >>= (int x) {
        FPS res;
        res.insert(res.end(), begin(*this) + x, end(*this));
        return *this = res;
    }
    inline mint eval(const mint& v){
        mint res = 0;
        for (int i = (int)this->size()-1; i >= 0; --i) {
            res *= v;
            res += (*this)[i];
        }
        return res;
    }
    inline friend FPS gcd(const FPS& f, const FPS& g) {
        if (g.empty()) return f;
        return gcd(g, f % g);
    }

    // advanced operation
    // df/dx
    inline friend FPS diff(const FPS& f) {
        int n = (int)f.size();
        FPS res(n-1);
        for (int i = 1; i < n; ++i) res[i-1] = f[i] * i;
        return res;
    }

    // \int f dx
    inline friend FPS integral(const FPS& f) {
        int n = (int)f.size();
        FPS res(n+1, 0);
        for (int i = 0; i < n; ++i) res[i+1] = f[i] / (i+1);
        return res;
    }

    // inv(f), f[0] must not be 0
    inline friend FPS inv(const FPS& f, int deg) {
        assert(f[0] != 0);
        if (deg < 0) deg = (int)f.size();
        FPS res({mint(1) / f[0]});
        for (int i = 1; i < deg; i <<= 1) {
            res = (res + res - res * res * f.pre(i << 1)).pre(i << 1);
        }
        res.resize(deg);
        return res;
    }
    inline friend FPS inv(const FPS& f) {
        return inv(f, f.size());
    }

    // division, r must be normalized (r.back() must not be 0)
    inline FPS& operator /= (const FPS& r) {
        assert(!r.empty());
        assert(r.back() != 0);
        this->normalize();
        if (this->size() < r.size()) {
            this->clear();
            return *this;
        }
        int need = (int)this->size() - (int)r.size() + 1;
        *this = ((*this).rev().pre(need) * inv(r.rev(), need)).pre(need).rev();
        return *this;
    }
    inline FPS& operator %= (const FPS &r) {
        assert(!r.empty());
        assert(r.back() != 0);
        this->normalize();
        FPS q = (*this) / r;
        return *this -= q * r;
    }
    inline FPS operator / (const FPS& r) const { return FPS(*this) /= r; }
    inline FPS operator % (const FPS& r) const { return FPS(*this) %= r; }

    // log(f) = \int f'/f dx, f[0] must be 1
    inline friend FPS log(const FPS& f, int deg) {
        assert(f[0] == 1);
        FPS res = integral(diff(f) * inv(f, deg));
        res.resize(deg);
        return res;
    }
    inline friend FPS log(const FPS& f) {
        return log(f, f.size());
    }

    // exp(f), f[0] must be 0
    inline friend FPS exp(const FPS& f, int deg) {
        assert(f[0] == 0);
        FPS res(1, 1);
        for (int i = 1; i < deg; i <<= 1) {
            res = res * (f.pre(i<<1) - log(res, i<<1) + 1).pre(i<<1);
        }
        res.resize(deg);
        return res;
    }
    inline friend FPS exp(const FPS& f) {
        return exp(f, f.size());
    }

    // pow(f) = exp(e * log f)
    inline friend FPS pow(const FPS& f, long long e, int deg) {
        long long i = 0;
        while (i < (int)f.size() && f[i] == 0) ++i;
        if (i == (int)f.size()) return FPS(deg, 0);
        if (i * e >= deg) return FPS(deg, 0);
        mint k = f[i];
        FPS res = exp(log((f >> i) / k) * e) * modpow(k, e) << (e * i);
        res.resize(deg);
        return res;
    }
    inline friend FPS pow(const FPS& f, long long e) {
        return pow(f, e, f.size());
    }

    // sqrt(f), f[0] must be 1
    inline friend FPS sqrt_base(const FPS& f, int deg) {
        assert(f[0] == 1);
        mint inv2 = mint(1) / 2;
        FPS res(1, 1);
        for (int i = 1; i < deg; i <<= 1) {
            res = (res + f.pre(i << 1) * inv(res, i << 1)).pre(i << 1);
            for (mint& x : res) x *= inv2;
        }
        res.resize(deg);
        return res;
    }
    inline friend FPS sqrt_base(const FPS& f) {
        return sqrt_base(f, f.size());
    }
};

using mint = Fp<>;



////////////////////////////////////////
// solver
////////////////////////////////////////

FPS<mint> modpow(const FPS<mint> &f, long long n, const FPS<mint> &m) {
    if (n == 0) return FPS<mint>(1, 1);
    auto t = modpow(f, n / 2, m);
    t = (t * t) % m;
    if (n & 1) t = (t * f) % m;
    auto q = t / m;
    auto r = t % m;
    return t;
}

void AOJ2213() {
    long long N, P;
    while (cin >> N >> P) {
        if (N == 0) break;
        MODS[0] = P;
		
        FPS<mint> f(N+1);
        for (int i = 0; i < N+1; ++i) cin >> f[i];
        f.normalize();
        if (f.empty()) { 
            cout << P << endl;
            continue; 
        }
        
        FPS<mint> x(2, 0);
        x[1] = 1; // 多項式 x
        FPS<mint> g = modpow(x, P, f) - x;
        FPS<mint> res = gcd(f, g);
        cout << (int)res.size() - 1 << endl;
    }
}

int main() {
    AOJ2213();
}
accuracy: 1
time_ms: 60
memory_kb: 3640
final_rank: 10

code_snippet: //
// Formal Power Series (on runtime mod)
//
// verified:
//   Yosupo Judge
//     https://judge.yosupo.jp/problem/inv_of_formal_power_series
//
//   AOJ 2213 The Number of Solutions for a Polynomial
//     http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2213
//


#include <bits/stdc++.h>
using namespace std;

#define COUT(x) cout << #x << " = " << (x) << " (L" << __LINE__ << ")" << endl
template<class T1, class T2> ostream& operator << (ostream &s, pair<T1,T2> P)
{ return s << '<' << P.first << ", " << P.second << '>'; }
template<class T> ostream& operator << (ostream &s, vector<T> P)
{ for (int i = 0; i < P.size(); ++i) { if (i > 0) { s << " "; } s << P[i]; } return s; }
template<class T> ostream& operator << (ostream &s, vector<vector<T> > P)
{ for (int i = 0; i < P.size(); ++i) { s << endl << P[i]; } return s << endl; }
template<class T> ostream& operator << (ostream &s, set<T> P)
{ for(auto it : P) { s << "<" << it << "> "; } return s << endl; }
template<class T1, class T2> ostream& operator << (ostream &s, map<T1,T2> P)
{ for(auto it : P) { s << "<" << it.first << "->" << it.second << "> "; } return s << endl; }


// modint (replace MODS[0] on runtime)
vector<int> MODS = { 1000000007, 754974721, 167772161, 469762049 };
template<int IND = 0> struct Fp {
    long long val;
    constexpr Fp(long long v = 0) noexcept : val(v % MODS[IND]) {
        if (val < 0) val += MODS[IND];
    }
    constexpr int getmod() const { return MODS[IND]; }
    constexpr Fp operator - () const noexcept {
        return val ? MODS[IND] - val : 0;
    }
    constexpr Fp operator + (const Fp& r) const noexcept { return Fp(*this) += r; }
    constexpr Fp operator - (const Fp& r) const noexcept { return Fp(*this) -= r; }
    constexpr Fp operator * (const Fp& r) const noexcept { return Fp(*this) *= r; }
    constexpr Fp operator / (const Fp& r) const noexcept { return Fp(*this) /= r; }
    constexpr Fp& operator += (const Fp& r) noexcept {
        val += r.val;
        if (val >= MODS[IND]) val -= MODS[IND];
        return *this;
    }
    constexpr Fp& operator -= (const Fp& r) noexcept {
        val -= r.val;
        if (val < 0) val += MODS[IND];
        return *this;
    }
    constexpr Fp& operator *= (const Fp& r) noexcept {
        val = val * r.val % MODS[IND];
        return *this;
    }
    constexpr Fp& operator /= (const Fp& r) noexcept {
        long long a = r.val, b = MODS[IND], u = 1, v = 0;
        while (b) {
            long long t = a / b;
            a -= t * b; swap(a, b);
            u -= t * v; swap(u, v);
        }
        val = val * u % MODS[IND];
        if (val < 0) val += MODS[IND];
        return *this;
    }
    constexpr bool operator == (const Fp& r) const noexcept {
        return this->val == r.val;
    }
    constexpr bool operator != (const Fp& r) const noexcept {
        return this->val != r.val;
    }
    friend constexpr istream& operator >> (istream& is, Fp<IND>& x) noexcept {
        is >> x.val;
        x.val %= MODS[IND];
        if (x.val < 0) x.val += MODS[IND];
        return is;
    }
    friend constexpr ostream& operator << (ostream& os, const Fp<IND>& x) noexcept {
        return os << x.val;
    }
    friend constexpr Fp<IND> modpow(const Fp<IND>& r, long long n) noexcept {
        if (n == 0) return 1;
        auto t = modpow(r, n / 2);
        t = t * t;
        if (n & 1) t = t * r;
        return t;
    }
    friend constexpr Fp<IND> modinv(const Fp<IND>& r) noexcept {
        long long a = r.val, b = MODS[IND], u = 1, v = 0;
        while (b) {
            long long t = a / b;
            a -= t * b, swap(a, b);
            u -= t * v, swap(u, v);
        }
        return Fp<IND>(u);
    }
};

namespace NTT {    
    long long modpow(long long a, long long n, int mod) {
        long long res = 1;
        while (n > 0) {
            if (n & 1) res = res * a % mod;
            a = a * a % mod;
            n >>= 1;
        }
        return res;
    }

    long long modinv(long long a, int mod) {
        long long b = mod, u = 1, v = 0;
        while (b) {
            long long t = a / b;
            a -= t * b, swap(a, b);
            u -= t * v, swap(u, v);
        }
        u %= mod;
        if (u < 0) u += mod;
        return u;
    }

    int calc_primitive_root(int mod) {
        if (mod == 2) return 1;
        if (mod == 167772161) return 3;
        if (mod == 469762049) return 3;
        if (mod == 754974721) return 11;
        if (mod == 998244353) return 3;
        int divs[20] = {};
        divs[0] = 2;
        int cnt = 1;
        long long x = (mod - 1) / 2;
        while (x % 2 == 0) x /= 2;
        for (long long i = 3; i * i <= x; i += 2) {
            if (x % i == 0) {
                divs[cnt++] = i;
                while (x % i == 0) x /= i;
            }
        }
        if (x > 1) divs[cnt++] = x;
        for (int g = 2;; g++) {
            bool ok = true;
            for (int i = 0; i < cnt; i++) {
                if (modpow(g, (mod - 1) / divs[i], mod) == 1) {
                    ok = false;
                    break;
                }
            }
            if (ok) return g;
        }
    }

    int get_fft_size(int N, int M) {
        int size_a = 1, size_b = 1;
        while (size_a < N) size_a <<= 1;
        while (size_b < M) size_b <<= 1;
        return max(size_a, size_b) << 1;
    }

    // number-theoretic transform
    set<int> setmod;
    template<class mint> void trans(vector<mint>& v, bool inv = false) {
        if (v.empty()) return;
        int N = (int)v.size();
        int MOD = v[0].getmod();
        int PR = calc_primitive_root(MOD);
        static vector<long long> vbw(30), vibw(30);
        if (!setmod.count(MOD)) {
            setmod.insert(MOD);
            for (int k = 0; k < 30; ++k) {
                vbw[k] = modpow(PR, (MOD - 1) >> (k + 1), MOD);
                vibw[k] = modinv(vbw[k], MOD);
            }
        }
        for (int i = 0, j = 1; j < N - 1; j++) {
            for (int k = N >> 1; k > (i ^= k); k >>= 1);
            if (i > j) swap(v[i], v[j]);
        }
        for (int k = 0, t = 2; t <= N; ++k, t <<= 1) {
            long long bw = vbw[k];
            if (inv) bw = vibw[k];
            for (int i = 0; i < N; i += t) {
                mint w = 1;
                for (int j = 0; j < t/2; ++j) {
                    int j1 = i + j, j2 = i + j + t/2;
                    mint c1 = v[j1], c2 = v[j2] * w;
                    v[j1] = c1 + c2;
                    v[j2] = c1 - c2;
                    w *= bw;
                }
            }
        }
        if (inv) {
            long long invN = modinv(N, MOD);
            for (int i = 0; i < N; ++i) v[i] = v[i] * invN;
        }
    }

    // for garner
    static constexpr int IND1 = 1; //754974721;
    static constexpr int IND2 = 2; //167772161;
    static constexpr int IND3 = 3; //469762049;
    using mint1 = Fp<IND1>;
    using mint2 = Fp<IND2>;
    using mint3 = Fp<IND3>;
    static const mint2 imod1 = 95869806; // modinv(MOD1, MOD2);
    static const mint3 imod2 = 104391568; // modinv(MOD2, MOD3);
    static const mint3 imod12 = 187290749; // imod2 / MOD1;

    // small case (T = mint, long long)
    template<class T> vector<T> naive_mul 
    (const vector<T>& A, const vector<T>& B) {
        if (A.empty() || B.empty()) return {};
        int N = (int)A.size(), M = (int)B.size();
        vector<T> res(N + M - 1);
        for (int i = 0; i < N; ++i)
            for (int j = 0; j < M; ++j)
                res[i + j] += A[i] * B[j];
        return res;
    }

    // mint
    template<class mint> vector<mint> mul
    (const vector<mint>& A, const vector<mint>& B) {
        if (A.empty() || B.empty()) return {};
        int N = (int)A.size(), M = (int)B.size();
        if (min(N, M) < 80) return naive_mul(A, B);
        int MOD = A[0].getmod();
        int size_fft = get_fft_size(N, M);
        if (MOD == 998244353) {
            vector<mint> a(size_fft), b(size_fft), c(size_fft);
            for (int i = 0; i < N; ++i) a[i] = A[i];
            for (int i = 0; i < M; ++i) b[i] = B[i];
            trans(a), trans(b);
            vector<mint> res(size_fft);
            for (int i = 0; i < size_fft; ++i) res[i] = a[i] * b[i];
            trans(res, true);
            res.resize(N + M - 1);
            return res;
        }
        vector<mint1> a1(size_fft, 0), b1(size_fft, 0), c1(size_fft, 0);
        vector<mint2> a2(size_fft, 0), b2(size_fft, 0), c2(size_fft, 0);
        vector<mint3> a3(size_fft, 0), b3(size_fft, 0), c3(size_fft, 0);
        for (int i = 0; i < N; ++i)
            a1[i] = A[i].val, a2[i] = A[i].val, a3[i] = A[i].val;
        for (int i = 0; i < M; ++i)
            b1[i] = B[i].val, b2[i] = B[i].val, b3[i] = B[i].val;
        trans(a1), trans(a2), trans(a3), trans(b1), trans(b2), trans(b3);
        for (int i = 0; i < size_fft; ++i) {
            c1[i] = a1[i] * b1[i];
            c2[i] = a2[i] * b2[i];
            c3[i] = a3[i] * b3[i];
        }
        trans(c1, true), trans(c2, true), trans(c3, true);
        mint mod1 = MODS[IND1], mod12 = mod1 * MODS[IND2];
        vector<mint> res(N + M - 1);
        for (int i = 0; i < N + M - 1; ++i) {
            int y1 = c1[i].val;
            int y2 = (imod1 * (c2[i] - y1)).val;
            int y3 = (imod12 * (c3[i] - y1) - imod2 * y2).val;
            res[i] = mod12 * y3 + mod1 * y2 + y1;
        }
        return res;
    }
};

// Binomial Coefficient
template<class T> struct BiCoef {
    vector<T> fact_, inv_, finv_;
    constexpr BiCoef() {}
    constexpr BiCoef(int n) noexcept : fact_(n, 1), inv_(n, 1), finv_(n, 1) {
        init(n);
    }
    constexpr void init(int n) noexcept {
        fact_.assign(n, 1), inv_.assign(n, 1), finv_.assign(n, 1);
        int MOD = fact_[0].getmod();
        for(int i = 2; i < n; i++){
            fact_[i] = fact_[i-1] * i;
            inv_[i] = -inv_[MOD%i] * (MOD/i);
            finv_[i] = finv_[i-1] * inv_[i];
        }
    }
    constexpr T com(int n, int k) const noexcept {
        if (n < k || n < 0 || k < 0) return 0;
        return fact_[n] * finv_[k] * finv_[n-k];
    }
    constexpr T fact(int n) const noexcept {
        if (n < 0) return 0;
        return fact_[n];
    }
    constexpr T inv(int n) const noexcept {
        if (n < 0) return 0;
        return inv_[n];
    }
    constexpr T finv(int n) const noexcept {
        if (n < 0) return 0;
        return finv_[n];
    }
};

// Formal Power Series
template <typename mint> struct FPS : vector<mint> {
    using vector<mint>::vector;
 
    // constructor
    FPS(const vector<mint>& r) : vector<mint>(r) {}
 
    // core operator
    inline FPS pre(int siz) const {
        return FPS(begin(*this), begin(*this) + min((int)this->size(), siz));
    }
    inline FPS rev() const {
        FPS res = *this;
        reverse(begin(res), end(res));
        return res;
    }
    inline FPS& normalize() {
        while (!this->empty() && this->back() == 0) this->pop_back();
        return *this;
    }
 
    // basic operator
    inline FPS operator - () const noexcept {
        FPS res = (*this);
        for (int i = 0; i < (int)res.size(); ++i) res[i] = -res[i];
        return res;
    }
    inline FPS operator + (const mint& v) const { return FPS(*this) += v; }
    inline FPS operator + (const FPS& r) const { return FPS(*this) += r; }
    inline FPS operator - (const mint& v) const { return FPS(*this) -= v; }
    inline FPS operator - (const FPS& r) const { return FPS(*this) -= r; }
    inline FPS operator * (const mint& v) const { return FPS(*this) *= v; }
    inline FPS operator * (const FPS& r) const { return FPS(*this) *= r; }
    inline FPS operator / (const mint& v) const { return FPS(*this) /= v; }
    inline FPS operator << (int x) const { return FPS(*this) <<= x; }
    inline FPS operator >> (int x) const { return FPS(*this) >>= x; }
    inline FPS& operator += (const mint& v) {
        if (this->empty()) this->resize(1);
        (*this)[0] += v;
        return *this;
    }
    inline FPS& operator += (const FPS& r) {
        if (r.size() > this->size()) this->resize(r.size());
        for (int i = 0; i < (int)r.size(); ++i) (*this)[i] += r[i];
        return this->normalize();
    }
    inline FPS& operator -= (const mint& v) {
        if (this->empty()) this->resize(1);
        (*this)[0] -= v;
        return *this;
    }
    inline FPS& operator -= (const FPS& r) {
        if (r.size() > this->size()) this->resize(r.size());
        for (int i = 0; i < (int)r.size(); ++i) (*this)[i] -= r[i];
        return this->normalize();
    }
    inline FPS& operator *= (const mint& v) {
        for (int i = 0; i < (int)this->size(); ++i) (*this)[i] *= v;
        return *this;
    }
    inline FPS& operator *= (const FPS& r) {
        return *this = NTT::mul((*this), r);
    }
    inline FPS& operator /= (const mint& v) {
        assert(v != 0);
        mint iv = modinv(v);
        for (int i = 0; i < (int)this->size(); ++i) (*this)[i] *= iv;
        return *this;
    }
    inline FPS& operator <<= (int x) {
        FPS res(x, 0);
        res.insert(res.end(), begin(*this), end(*this));
        return *this = res;
    }
    inline FPS& operator >>= (int x) {
        FPS res;
        res.insert(res.end(), begin(*this) + x, end(*this));
        return *this = res;
    }
    inline mint eval(const mint& v){
        mint res = 0;
        for (int i = (int)this->size()-1; i >= 0; --i) {
            res *= v;
            res += (*this)[i];
        }
        return res;
    }
    inline friend FPS gcd(const FPS& f, const FPS& g) {
        if (g.empty()) return f;
        return gcd(g, f % g);
    }

    // advanced operation
    // df/dx
    inline friend FPS diff(const FPS& f) {
        int n = (int)f.size();
        FPS res(n-1);
        for (int i = 1; i < n; ++i) res[i-1] = f[i] * i;
        return res;
    }

    // \int f dx
    inline friend FPS integral(const FPS& f) {
        int n = (int)f.size();
        FPS res(n+1, 0);
        for (int i = 0; i < n; ++i) res[i+1] = f[i] / (i+1);
        return res;
    }

    // inv(f), f[0] must not be 0
    inline friend FPS inv(const FPS& f, int deg) {
        assert(f[0] != 0);
        if (deg < 0) deg = (int)f.size();
        FPS res({mint(1) / f[0]});
        for (int i = 1; i < deg; i <<= 1) {
            res = (res + res - res * res * f.pre(i << 1)).pre(i << 1);
        }
        return res.pre(deg);
    }
    inline friend FPS inv(const FPS& f) {
        return inv(f, f.size());
    }

    // division, r must be normalized (r.back() must not be 0)
    inline FPS& operator /= (const FPS& r) {
        assert(!r.empty());
        assert(r.back() != 0);
        this->normalize();
        if (this->size() < r.size()) {
            this->clear();
            return *this;
        }
        int need = (int)this->size() - (int)r.size() + 1;
        *this = ((*this).rev().pre(need) * inv(r.rev(), need)).pre(need).rev();
        return *this;
    }
    inline FPS& operator %= (const FPS &r) {
        assert(!r.empty());
        assert(r.back() != 0);
        this->normalize();
        FPS q = (*this) / r;
        return *this -= q * r;
    }
    inline FPS operator / (const FPS& r) const { return FPS(*this) /= r; }
    inline FPS operator % (const FPS& r) const { return FPS(*this) %= r; }

    // log(f) = \int f'/f dx, f[0] must be 1
    inline friend FPS log(const FPS& f, int deg) {
        assert(f[0] == 1);
        FPS res = integral(diff(f) * inv(f, deg));
        res.resize(deg);
        return res;
    }
    inline friend FPS log(const FPS& f) {
        return log(f, f.size());
    }

    // exp(f), f[0] must be 0
    inline friend FPS exp(const FPS& f, int deg) {
        assert(f[0] == 0);
        FPS res(1, 1);
        for (int i = 1; i < deg; i <<= 1) {
            res = res * (f.pre(i<<1) - log(res, i<<1) + 1).pre(i<<1);
        }
        res.resize(deg);
        return res;
    }
    inline friend FPS exp(const FPS& f) {
        return exp(f, f.size());
    }

    // pow(f) = exp(e * log f)
    inline friend FPS pow(const FPS& f, long long e, int deg) {
        long long i = 0;
        while (i < (int)f.size() && f[i] == 0) ++i;
        if (i == (int)f.size()) return FPS(deg, 0);
        if (i * e >= deg) return FPS(deg, 0);
        mint k = f[i];
        FPS res = exp(log((f >> i) / k) * e) * modpow(k, e) << (e * i);
        res.resize(deg);
        return res;
    }
    inline friend FPS pow(const FPS& f, long long e) {
        return pow(f, e, f.size());
    }

    // sqrt(f), f[0] must be 1
    inline friend FPS sqrt(const FPS& f, int deg) {
        assert(f[0] == 1);
        int siz = 1;
        mint inv2 = mint(1) / 2;
        FPS res(1, 1);
        while (siz < deg) {
            siz <<= 1;
            FPS tmp(min(siz, (int)f.size()));
            for (int i = 0; i < (int)tmp.size(); ++i) tmp[i] = f[i];
            res += tmp * inv(f, siz);
            res.resize(siz);
            for (mint& x : res) res *= inv2;
        }
        return res;
    }
    inline friend FPS sqrt(const FPS& f) {
        return sqrt(f, f.size());
    }
};

using mint = Fp<>;

FPS<mint> modpow(const FPS<mint> &f, long long n, const FPS<mint> &m) {
    if (n == 0) return FPS<mint>(1, 1);
    auto t = modpow(f, n / 2, m);
    t = (t * t) % m;
    if (n & 1) t = (t * f) % m;
    auto q = t / m;
    auto r = t % m;
    return t;
}

int main() {
    long long N, P;
    while (cin >> N >> P) {
        if (N == 0) break;
        MODS[0] = P;
		
        FPS<mint> f(N+1);
        for (int i = 0; i < N+1; ++i) cin >> f[i];
        f.normalize();
        if (f.empty()) { 
            cout << P << endl;
            continue; 
        }
        
        FPS<mint> x(2, 0);
        x[1] = 1; // 多項式 x
        FPS<mint> g = modpow(x, P, f) - x;
        FPS<mint> res = gcd(f, g);
        cout << (int)res.size() - 1 << endl;
    }
}
accuracy: 1
time_ms: 60
memory_kb: 3332
final_rank: 8

code_snippet: //
// Formal Power Series (on runtime mod)
//
// verified:
//   Yosupo Judge
//     https://judge.yosupo.jp/problem/inv_of_formal_power_series
//
//   AOJ 2213 The Number of Solutions for a Polynomial
//     http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2213
//


#include <bits/stdc++.h>
using namespace std;

#define COUT(x) cout << #x << " = " << (x) << " (L" << __LINE__ << ")" << endl
template<class T1, class T2> ostream& operator << (ostream &s, pair<T1,T2> P)
{ return s << '<' << P.first << ", " << P.second << '>'; }
template<class T> ostream& operator << (ostream &s, vector<T> P)
{ for (int i = 0; i < P.size(); ++i) { if (i > 0) { s << " "; } s << P[i]; } return s; }
template<class T> ostream& operator << (ostream &s, vector<vector<T> > P)
{ for (int i = 0; i < P.size(); ++i) { s << endl << P[i]; } return s << endl; }
template<class T> ostream& operator << (ostream &s, set<T> P)
{ for(auto it : P) { s << "<" << it << "> "; } return s << endl; }
template<class T1, class T2> ostream& operator << (ostream &s, map<T1,T2> P)
{ for(auto it : P) { s << "<" << it.first << "->" << it.second << "> "; } return s << endl; }


// modint (replace MODS[0] on runtime)
vector<int> MODS = { 1000000007, 754974721, 167772161, 469762049 };
template<int IND = 0> struct Fp {
    long long val;
    constexpr Fp(long long v = 0) noexcept : val(v % MODS[IND]) {
        if (val < 0) val += MODS[IND];
    }
    constexpr int getmod() const { return MODS[IND]; }
    constexpr Fp operator - () const noexcept {
        return val ? MODS[IND] - val : 0;
    }
    constexpr Fp operator + (const Fp& r) const noexcept { return Fp(*this) += r; }
    constexpr Fp operator - (const Fp& r) const noexcept { return Fp(*this) -= r; }
    constexpr Fp operator * (const Fp& r) const noexcept { return Fp(*this) *= r; }
    constexpr Fp operator / (const Fp& r) const noexcept { return Fp(*this) /= r; }
    constexpr Fp& operator += (const Fp& r) noexcept {
        val += r.val;
        if (val >= MODS[IND]) val -= MODS[IND];
        return *this;
    }
    constexpr Fp& operator -= (const Fp& r) noexcept {
        val -= r.val;
        if (val < 0) val += MODS[IND];
        return *this;
    }
    constexpr Fp& operator *= (const Fp& r) noexcept {
        val = val * r.val % MODS[IND];
        return *this;
    }
    constexpr Fp& operator /= (const Fp& r) noexcept {
        long long a = r.val, b = MODS[IND], u = 1, v = 0;
        while (b) {
            long long t = a / b;
            a -= t * b; swap(a, b);
            u -= t * v; swap(u, v);
        }
        val = val * u % MODS[IND];
        if (val < 0) val += MODS[IND];
        return *this;
    }
    constexpr bool operator == (const Fp& r) const noexcept {
        return this->val == r.val;
    }
    constexpr bool operator != (const Fp& r) const noexcept {
        return this->val != r.val;
    }
    friend constexpr istream& operator >> (istream& is, Fp<IND>& x) noexcept {
        is >> x.val;
        x.val %= MODS[IND];
        if (x.val < 0) x.val += MODS[IND];
        return is;
    }
    friend constexpr ostream& operator << (ostream& os, const Fp<IND>& x) noexcept {
        return os << x.val;
    }
    friend constexpr Fp<IND> modpow(const Fp<IND>& r, long long n) noexcept {
        if (n == 0) return 1;
        auto t = modpow(r, n / 2);
        t = t * t;
        if (n & 1) t = t * r;
        return t;
    }
    friend constexpr Fp<IND> modinv(const Fp<IND>& r) noexcept {
        long long a = r.val, b = MODS[IND], u = 1, v = 0;
        while (b) {
            long long t = a / b;
            a -= t * b, swap(a, b);
            u -= t * v, swap(u, v);
        }
        return Fp<IND>(u);
    }
};

namespace NTT {    
    long long modpow(long long a, long long n, int mod) {
        long long res = 1;
        while (n > 0) {
            if (n & 1) res = res * a % mod;
            a = a * a % mod;
            n >>= 1;
        }
        return res;
    }

    long long modinv(long long a, int mod) {
        long long b = mod, u = 1, v = 0;
        while (b) {
            long long t = a / b;
            a -= t * b, swap(a, b);
            u -= t * v, swap(u, v);
        }
        u %= mod;
        if (u < 0) u += mod;
        return u;
    }

    int calc_primitive_root(int mod) {
        if (mod == 2) return 1;
        if (mod == 167772161) return 3;
        if (mod == 469762049) return 3;
        if (mod == 754974721) return 11;
        if (mod == 998244353) return 3;
        int divs[20] = {};
        divs[0] = 2;
        int cnt = 1;
        long long x = (mod - 1) / 2;
        while (x % 2 == 0) x /= 2;
        for (long long i = 3; i * i <= x; i += 2) {
            if (x % i == 0) {
                divs[cnt++] = i;
                while (x % i == 0) x /= i;
            }
        }
        if (x > 1) divs[cnt++] = x;
        for (int g = 2;; g++) {
            bool ok = true;
            for (int i = 0; i < cnt; i++) {
                if (modpow(g, (mod - 1) / divs[i], mod) == 1) {
                    ok = false;
                    break;
                }
            }
            if (ok) return g;
        }
    }

    int get_fft_size(int N, int M) {
        int size_a = 1, size_b = 1;
        while (size_a < N) size_a <<= 1;
        while (size_b < M) size_b <<= 1;
        return max(size_a, size_b) << 1;
    }

    // number-theoretic transform
    set<int> setmod;
    template<class mint> void trans(vector<mint>& v, bool inv = false) {
        if (v.empty()) return;
        int N = (int)v.size();
        int MOD = v[0].getmod();
        int PR = calc_primitive_root(MOD);
        static vector<long long> vbw(30), vibw(30);
        if (!setmod.count(MOD)) {
            setmod.insert(MOD);
            for (int k = 0; k < 30; ++k) {
                vbw[k] = modpow(PR, (MOD - 1) >> (k + 1), MOD);
                vibw[k] = modinv(vbw[k], MOD);
            }
        }
        for (int i = 0, j = 1; j < N - 1; j++) {
            for (int k = N >> 1; k > (i ^= k); k >>= 1);
            if (i > j) swap(v[i], v[j]);
        }
        for (int k = 0, t = 2; t <= N; ++k, t <<= 1) {
            long long bw = vbw[k];
            if (inv) bw = vibw[k];
            for (int i = 0; i < N; i += t) {
                mint w = 1;
                for (int j = 0; j < t/2; ++j) {
                    int j1 = i + j, j2 = i + j + t/2;
                    mint c1 = v[j1], c2 = v[j2] * w;
                    v[j1] = c1 + c2;
                    v[j2] = c1 - c2;
                    w *= bw;
                }
            }
        }
        if (inv) {
            long long invN = modinv(N, MOD);
            for (int i = 0; i < N; ++i) v[i] = v[i] * invN;
        }
    }

    // for garner
    static constexpr int IND1 = 1; //754974721;
    static constexpr int IND2 = 2; //167772161;
    static constexpr int IND3 = 3; //469762049;
    using mint1 = Fp<IND1>;
    using mint2 = Fp<IND2>;
    using mint3 = Fp<IND3>;
    static const mint2 imod1 = 95869806; // modinv(MOD1, MOD2);
    static const mint3 imod2 = 104391568; // modinv(MOD2, MOD3);
    static const mint3 imod12 = 187290749; // imod2 / MOD1;

    // small case (T = mint, long long)
    template<class T> vector<T> naive_mul 
    (const vector<T>& A, const vector<T>& B) {
        if (A.empty() || B.empty()) return {};
        int N = (int)A.size(), M = (int)B.size();
        vector<T> res(N + M - 1);
        for (int i = 0; i < N; ++i)
            for (int j = 0; j < M; ++j)
                res[i + j] += A[i] * B[j];
        return res;
    }

    // mint
    template<class mint> vector<mint> mul
    (const vector<mint>& A, const vector<mint>& B) {
        if (A.empty() || B.empty()) return {};
        int N = (int)A.size(), M = (int)B.size();
        if (min(N, M) < 80) return naive_mul(A, B);
        int MOD = A[0].getmod();
        int size_fft = get_fft_size(N, M);
        if (MOD == 998244353) {
            vector<mint> a(size_fft), b(size_fft), c(size_fft);
            for (int i = 0; i < N; ++i) a[i] = A[i];
            for (int i = 0; i < M; ++i) b[i] = B[i];
            trans(a), trans(b);
            vector<mint> res(size_fft);
            for (int i = 0; i < size_fft; ++i) res[i] = a[i] * b[i];
            trans(res, true);
            res.resize(N + M - 1);
            return res;
        }
        vector<mint1> a1(size_fft, 0), b1(size_fft, 0), c1(size_fft, 0);
        vector<mint2> a2(size_fft, 0), b2(size_fft, 0), c2(size_fft, 0);
        vector<mint3> a3(size_fft, 0), b3(size_fft, 0), c3(size_fft, 0);
        for (int i = 0; i < N; ++i)
            a1[i] = A[i].val, a2[i] = A[i].val, a3[i] = A[i].val;
        for (int i = 0; i < M; ++i)
            b1[i] = B[i].val, b2[i] = B[i].val, b3[i] = B[i].val;
        trans(a1), trans(a2), trans(a3), trans(b1), trans(b2), trans(b3);
        for (int i = 0; i < size_fft; ++i) {
            c1[i] = a1[i] * b1[i];
            c2[i] = a2[i] * b2[i];
            c3[i] = a3[i] * b3[i];
        }
        trans(c1, true), trans(c2, true), trans(c3, true);
        mint mod1 = MODS[IND1], mod12 = mod1 * MODS[IND2];
        vector<mint> res(N + M - 1);
        for (int i = 0; i < N + M - 1; ++i) {
            int y1 = c1[i].val;
            int y2 = (imod1 * (c2[i] - y1)).val;
            int y3 = (imod12 * (c3[i] - y1) - imod2 * y2).val;
            res[i] = mod12 * y3 + mod1 * y2 + y1;
        }
        return res;
    }
};

// Binomial Coefficient
template<class T> struct BiCoef {
    vector<T> fact_, inv_, finv_;
    constexpr BiCoef() {}
    constexpr BiCoef(int n) noexcept : fact_(n, 1), inv_(n, 1), finv_(n, 1) {
        init(n);
    }
    constexpr void init(int n) noexcept {
        fact_.assign(n, 1), inv_.assign(n, 1), finv_.assign(n, 1);
        int MOD = fact_[0].getmod();
        for(int i = 2; i < n; i++){
            fact_[i] = fact_[i-1] * i;
            inv_[i] = -inv_[MOD%i] * (MOD/i);
            finv_[i] = finv_[i-1] * inv_[i];
        }
    }
    constexpr T com(int n, int k) const noexcept {
        if (n < k || n < 0 || k < 0) return 0;
        return fact_[n] * finv_[k] * finv_[n-k];
    }
    constexpr T fact(int n) const noexcept {
        if (n < 0) return 0;
        return fact_[n];
    }
    constexpr T inv(int n) const noexcept {
        if (n < 0) return 0;
        return inv_[n];
    }
    constexpr T finv(int n) const noexcept {
        if (n < 0) return 0;
        return finv_[n];
    }
};

// Formal Power Series
template <typename mint> struct FPS : vector<mint> {
    using vector<mint>::vector;
 
    // constructor
    FPS(const vector<mint>& r) : vector<mint>(r) {}
 
    // core operator
    inline FPS pre(int siz) const {
        return FPS(begin(*this), begin(*this) + min((int)this->size(), siz));
    }
    inline FPS rev() const {
        FPS res = *this;
        reverse(begin(res), end(res));
        return res;
    }
    inline FPS& normalize() {
        while (!this->empty() && this->back() == 0) this->pop_back();
        return *this;
    }
 
    // basic operator
    inline FPS operator - () const noexcept {
        FPS res = (*this);
        for (int i = 0; i < (int)res.size(); ++i) res[i] = -res[i];
        return res;
    }
    inline FPS operator + (const mint& v) const { return FPS(*this) += v; }
    inline FPS operator + (const FPS& r) const { return FPS(*this) += r; }
    inline FPS operator - (const mint& v) const { return FPS(*this) -= v; }
    inline FPS operator - (const FPS& r) const { return FPS(*this) -= r; }
    inline FPS operator * (const mint& v) const { return FPS(*this) *= v; }
    inline FPS operator * (const FPS& r) const { return FPS(*this) *= r; }
    inline FPS operator / (const mint& v) const { return FPS(*this) /= v; }
    inline FPS operator / (const FPS& r) const { return FPS(*this) /= r; }
    inline FPS operator % (const FPS& r) const { return FPS(*this) %= r; }
    inline FPS operator << (int x) const { return FPS(*this) <<= x; }
    inline FPS operator >> (int x) const { return FPS(*this) >>= x; }
    inline FPS& operator += (const mint& v) {
        if (this->empty()) this->resize(1);
        (*this)[0] += v;
        return *this;
    }
    inline FPS& operator += (const FPS& r) {
        if (r.size() > this->size()) this->resize(r.size());
        for (int i = 0; i < (int)r.size(); ++i) (*this)[i] += r[i];
        return this->normalize();
    }
    inline FPS& operator -= (const mint& v) {
        if (this->empty()) this->resize(1);
        (*this)[0] -= v;
        return *this;
    }
    inline FPS& operator -= (const FPS& r) {
        if (r.size() > this->size()) this->resize(r.size());
        for (int i = 0; i < (int)r.size(); ++i) (*this)[i] -= r[i];
        return this->normalize();
    }
    inline FPS& operator *= (const mint& v) {
        for (int i = 0; i < (int)this->size(); ++i) (*this)[i] *= v;
        return *this;
    }
    inline FPS& operator *= (const FPS& r) {
        return *this = NTT::mul((*this), r);
    }
    inline FPS& operator /= (const mint& v) {
        assert(v != 0);
        mint iv = modinv(v);
        for (int i = 0; i < (int)this->size(); ++i) (*this)[i] *= iv;
        return *this;
    }
    inline FPS& operator /= (const FPS& r) {
        if (this->size() < r.size()) {
            this->clear();
            return *this;
        }
        int need = (int)this->size() - (int)r.size() + 1;
        *this = (this->rev().pre(need) * inv(r.rev(), need)).pre(need).rev();
        return *this;
    }
    inline FPS& operator %= (const FPS &r) {
        FPS q = (*this) / r;
        return *this -= q * r;
    }
    inline FPS& operator <<= (int x) {
        FPS res(x, 0);
        res.insert(res.end(), begin(*this), end(*this));
        return *this = res;
    }
    inline FPS& operator >>= (int x) {
        FPS res;
        res.insert(res.end(), begin(*this) + x, end(*this));
        return *this = res;
    }
    inline mint eval(const mint& v){
        mint res = 0;
        for (int i = (int)this->size()-1; i >= 0; --i) {
            res *= v;
            res += (*this)[i];
        }
        return res;
    }
    inline friend FPS gcd(const FPS& f, const FPS& g) {
        if (g.empty()) return f;
        return gcd(g, f % g);
    }

    // advanced operation
    // df/dx
    inline friend FPS diff(const FPS& f) {
        int n = (int)f.size();
        FPS res(n-1);
        for (int i = 1; i < n; ++i) res[i-1] = f[i] * i;
        return res;
    }

    // \int f dx
    inline friend FPS integral(const FPS& f) {
        int n = (int)f.size();
        FPS res(n+1, 0);
        for (int i = 0; i < n; ++i) res[i+1] = f[i] / (i+1);
        return res;
    }

    // inv(f), f[0] must not be 0
    inline friend FPS inv(const FPS& f, int deg) {
        assert(f[0] != 0);
        if (deg < 0) deg = (int)f.size();
        FPS res({mint(1) / f[0]});
        for (int i = 1; i < deg; i <<= 1) {
            res = (res + res - res * res * f.pre(i << 1)).pre(i << 1);
        }
        return res.pre(deg);
    }
    inline friend FPS inv(const FPS& f) {
        return inv(f, f.size());
    }

    // log(f) = \int f'/f dx, f[0] must be 1
    inline friend FPS log(const FPS& f, int deg) {
        assert(f[0] == 1);
        FPS res = integral(diff(f) * inv(f, deg));
        res.resize(deg);
        return res;
    }
    inline friend FPS log(const FPS& f) {
        return log(f, f.size());
    }

    // exp(f), f[0] must be 0
    inline friend FPS exp(const FPS& f, int deg) {
        assert(f[0] == 0);
        FPS res(1, 1);
        for (int i = 1; i < deg; i <<= 1) {
            res = res * (f.pre(i<<1) - log(res, i<<1) + 1).pre(i<<1);
        }
        res.resize(deg);
        return res;
    }
    inline friend FPS exp(const FPS& f) {
        return exp(f, f.size());
    }

    // pow(f) = exp(e * log f)
    inline friend FPS pow(const FPS& f, long long e, int deg) {
        long long i = 0;
        while (i < (int)f.size() && f[i] == 0) ++i;
        if (i == (int)f.size()) return FPS(deg, 0);
        if (i * e >= deg) return FPS(deg, 0);
        mint k = f[i];
        FPS res = exp(log((f >> i) / k) * e) * modpow(k, e) << (e * i);
        res.resize(deg);
        return res;
    }
    inline friend FPS pow(const FPS& f, long long e) {
        return pow(f, e, f.size());
    }

    // sqrt(f), f[0] must be 1
    inline friend FPS sqrt(const FPS& f, int deg) {
        assert(f[0] == 1);
        int siz = 1;
        mint inv2 = mint(1) / 2;
        FPS res(1, 1);
        while (siz < deg) {
            siz <<= 1;
            FPS tmp(min(siz, (int)f.size()));
            for (int i = 0; i < (int)tmp.size(); ++i) tmp[i] = f[i];
            res += tmp * inv(f, siz);
            res.resize(siz);
            for (mint& x : res) res *= inv2;
        }
        return res;
    }
    inline friend FPS sqrt(const FPS& f) {
        return sqrt(f, f.size());
    }
};
using mint = Fp<>;

FPS<mint> modpow(const FPS<mint> &f, long long n, const FPS<mint> &m) {
    if (n == 0) return FPS<mint>(1, 1);
    auto t = modpow(f, n / 2, m);
    t = (t * t) % m;
    if (n & 1) t = (t * f) % m;
    auto q = t / m;
    auto r = t % m;
    return t;
}

int main() {
    long long N, P;
    while (cin >> N >> P) {
        if (N == 0) break;
        MODS[0] = P;
		
        FPS<mint> f(N+1);
        for (int i = 0; i < N+1; ++i) cin >> f[i];
        f.normalize();
        if (f.empty()) { 
            cout << P << endl;
            continue; 
        }
        
        FPS<mint> x(2, 0);
        x[1] = 1; // 多項式 x
        FPS<mint> g = modpow(x, P, f) - x;
        FPS<mint> res = gcd(f, g);
        cout << (int)res.size() - 1 << endl;
    }
}
accuracy: 1
time_ms: 60
memory_kb: 3500
final_rank: 9

code_snippet: //
// Formal Power Series (on runtime mod)
//
// verified:
//   Yosupo Judge
//     https://judge.yosupo.jp/problem/inv_of_formal_power_series
//
//   AOJ 2213 The Number of Solutions for a Polynomial
//     http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2213
//


#include <bits/stdc++.h>
using namespace std;

#define COUT(x) cout << #x << " = " << (x) << " (L" << __LINE__ << ")" << endl
template<class T1, class T2> ostream& operator << (ostream &s, pair<T1,T2> P)
{ return s << '<' << P.first << ", " << P.second << '>'; }
template<class T> ostream& operator << (ostream &s, vector<T> P)
{ for (int i = 0; i < P.size(); ++i) { if (i > 0) { s << " "; } s << P[i]; } return s; }
template<class T> ostream& operator << (ostream &s, vector<vector<T> > P)
{ for (int i = 0; i < P.size(); ++i) { s << endl << P[i]; } return s << endl; }
template<class T> ostream& operator << (ostream &s, set<T> P)
{ for(auto it : P) { s << "<" << it << "> "; } return s << endl; }
template<class T1, class T2> ostream& operator << (ostream &s, map<T1,T2> P)
{ for(auto it : P) { s << "<" << it.first << "->" << it.second << "> "; } return s << endl; }


// modint (replace MODS[0] on runtime)
vector<int> MODS = { 1000000007, 754974721, 167772161, 469762049 };
template<int IND = 0> struct Fp {
    long long val;
    constexpr Fp(long long v = 0) noexcept : val(v % MODS[IND]) {
        if (val < 0) val += MODS[IND];
    }
    constexpr int getmod() const { return MODS[IND]; }
    constexpr Fp operator - () const noexcept {
        return val ? MODS[IND] - val : 0;
    }
    constexpr Fp operator + (const Fp& r) const noexcept { return Fp(*this) += r; }
    constexpr Fp operator - (const Fp& r) const noexcept { return Fp(*this) -= r; }
    constexpr Fp operator * (const Fp& r) const noexcept { return Fp(*this) *= r; }
    constexpr Fp operator / (const Fp& r) const noexcept { return Fp(*this) /= r; }
    constexpr Fp& operator += (const Fp& r) noexcept {
        val += r.val;
        if (val >= MODS[IND]) val -= MODS[IND];
        return *this;
    }
    constexpr Fp& operator -= (const Fp& r) noexcept {
        val -= r.val;
        if (val < 0) val += MODS[IND];
        return *this;
    }
    constexpr Fp& operator *= (const Fp& r) noexcept {
        val = val * r.val % MODS[IND];
        return *this;
    }
    constexpr Fp& operator /= (const Fp& r) noexcept {
        long long a = r.val, b = MODS[IND], u = 1, v = 0;
        while (b) {
            long long t = a / b;
            a -= t * b; swap(a, b);
            u -= t * v; swap(u, v);
        }
        val = val * u % MODS[IND];
        if (val < 0) val += MODS[IND];
        return *this;
    }
    constexpr bool operator == (const Fp& r) const noexcept {
        return this->val == r.val;
    }
    constexpr bool operator != (const Fp& r) const noexcept {
        return this->val != r.val;
    }
    friend constexpr istream& operator >> (istream& is, Fp<IND>& x) noexcept {
        is >> x.val;
        x.val %= MODS[IND];
        if (x.val < 0) x.val += MODS[IND];
        return is;
    }
    friend constexpr ostream& operator << (ostream& os, const Fp<IND>& x) noexcept {
        return os << x.val;
    }
    friend constexpr Fp<IND> modpow(const Fp<IND>& r, long long n) noexcept {
        if (n == 0) return 1;
        auto t = modpow(r, n / 2);
        t = t * t;
        if (n & 1) t = t * r;
        return t;
    }
    friend constexpr Fp<IND> modinv(const Fp<IND>& r) noexcept {
        long long a = r.val, b = MODS[IND], u = 1, v = 0;
        while (b) {
            long long t = a / b;
            a -= t * b, swap(a, b);
            u -= t * v, swap(u, v);
        }
        return Fp<IND>(u);
    }
};

namespace NTT {    
    long long modpow(long long a, long long n, int mod) {
        long long res = 1;
        while (n > 0) {
            if (n & 1) res = res * a % mod;
            a = a * a % mod;
            n >>= 1;
        }
        return res;
    }

    long long modinv(long long a, int mod) {
        long long b = mod, u = 1, v = 0;
        while (b) {
            long long t = a / b;
            a -= t * b, swap(a, b);
            u -= t * v, swap(u, v);
        }
        u %= mod;
        if (u < 0) u += mod;
        return u;
    }

    int calc_primitive_root(int mod) {
        if (mod == 2) return 1;
        if (mod == 167772161) return 3;
        if (mod == 469762049) return 3;
        if (mod == 754974721) return 11;
        if (mod == 998244353) return 3;
        int divs[20] = {};
        divs[0] = 2;
        int cnt = 1;
        long long x = (mod - 1) / 2;
        while (x % 2 == 0) x /= 2;
        for (long long i = 3; i * i <= x; i += 2) {
            if (x % i == 0) {
                divs[cnt++] = i;
                while (x % i == 0) x /= i;
            }
        }
        if (x > 1) divs[cnt++] = x;
        for (int g = 2;; g++) {
            bool ok = true;
            for (int i = 0; i < cnt; i++) {
                if (modpow(g, (mod - 1) / divs[i], mod) == 1) {
                    ok = false;
                    break;
                }
            }
            if (ok) return g;
        }
    }

    int get_fft_size(int N, int M) {
        int size_a = 1, size_b = 1;
        while (size_a < N) size_a <<= 1;
        while (size_b < M) size_b <<= 1;
        return max(size_a, size_b) << 1;
    }

    // number-theoretic transform
    set<int> setmod;
    template<class mint> void trans(vector<mint>& v, bool inv = false) {
        if (v.empty()) return;
        int N = (int)v.size();
        int MOD = v[0].getmod();
        int PR = calc_primitive_root(MOD);
        static vector<long long> vbw(30), vibw(30);
        if (!setmod.count(MOD)) {
            setmod.insert(MOD);
            for (int k = 0; k < 30; ++k) {
                vbw[k] = modpow(PR, (MOD - 1) >> (k + 1), MOD);
                vibw[k] = modinv(vbw[k], MOD);
            }
        }
        for (int i = 0, j = 1; j < N - 1; j++) {
            for (int k = N >> 1; k > (i ^= k); k >>= 1);
            if (i > j) swap(v[i], v[j]);
        }
        for (int k = 0, t = 2; t <= N; ++k, t <<= 1) {
            long long bw = vbw[k];
            if (inv) bw = vibw[k];
            for (int i = 0; i < N; i += t) {
                mint w = 1;
                for (int j = 0; j < t/2; ++j) {
                    int j1 = i + j, j2 = i + j + t/2;
                    mint c1 = v[j1], c2 = v[j2] * w;
                    v[j1] = c1 + c2;
                    v[j2] = c1 - c2;
                    w *= bw;
                }
            }
        }
        if (inv) {
            long long invN = modinv(N, MOD);
            for (int i = 0; i < N; ++i) v[i] = v[i] * invN;
        }
    }

    // for garner
    static constexpr int IND1 = 1; //754974721;
    static constexpr int IND2 = 2; //167772161;
    static constexpr int IND3 = 3; //469762049;
    using mint1 = Fp<IND1>;
    using mint2 = Fp<IND2>;
    using mint3 = Fp<IND3>;
    static const mint2 imod1 = 95869806; // modinv(MOD1, MOD2);
    static const mint3 imod2 = 104391568; // modinv(MOD2, MOD3);
    static const mint3 imod12 = 187290749; // imod2 / MOD1;

    // small case (T = mint, long long)
    template<class T> vector<T> naive_mul 
    (const vector<T>& A, const vector<T>& B) {
        if (A.empty() || B.empty()) return {};
        int N = (int)A.size(), M = (int)B.size();
        vector<T> res(N + M - 1);
        for (int i = 0; i < N; ++i)
            for (int j = 0; j < M; ++j)
                res[i + j] += A[i] * B[j];
        return res;
    }

    // mint
    template<class mint> vector<mint> mul
    (const vector<mint>& A, const vector<mint>& B) {
        if (A.empty() || B.empty()) return {};
        int N = (int)A.size(), M = (int)B.size();
        if (min(N, M) < 80) return naive_mul(A, B);
        int MOD = A[0].getmod();
        int size_fft = get_fft_size(N, M);
        if (MOD == 998244353) {
            vector<mint> a(size_fft), b(size_fft), c(size_fft);
            for (int i = 0; i < N; ++i) a[i] = A[i];
            for (int i = 0; i < M; ++i) b[i] = B[i];
            trans(a), trans(b);
            vector<mint> res(size_fft);
            for (int i = 0; i < size_fft; ++i) res[i] = a[i] * b[i];
            trans(res, true);
            res.resize(N + M - 1);
            return res;
        }
        vector<mint1> a1(size_fft, 0), b1(size_fft, 0), c1(size_fft, 0);
        vector<mint2> a2(size_fft, 0), b2(size_fft, 0), c2(size_fft, 0);
        vector<mint3> a3(size_fft, 0), b3(size_fft, 0), c3(size_fft, 0);
        for (int i = 0; i < N; ++i)
            a1[i] = A[i].val, a2[i] = A[i].val, a3[i] = A[i].val;
        for (int i = 0; i < M; ++i)
            b1[i] = B[i].val, b2[i] = B[i].val, b3[i] = B[i].val;
        trans(a1), trans(a2), trans(a3), trans(b1), trans(b2), trans(b3);
        for (int i = 0; i < size_fft; ++i) {
            c1[i] = a1[i] * b1[i];
            c2[i] = a2[i] * b2[i];
            c3[i] = a3[i] * b3[i];
        }
        trans(c1, true), trans(c2, true), trans(c3, true);
        mint mod1 = MODS[IND1], mod12 = mod1 * MODS[IND2];
        vector<mint> res(N + M - 1);
        for (int i = 0; i < N + M - 1; ++i) {
            int y1 = c1[i].val;
            int y2 = (imod1 * (c2[i] - y1)).val;
            int y3 = (imod12 * (c3[i] - y1) - imod2 * y2).val;
            res[i] = mod12 * y3 + mod1 * y2 + y1;
        }
        return res;
    }
};

// Binomial Coefficient
template<class T> struct BiCoef {
    vector<T> fact_, inv_, finv_;
    constexpr BiCoef() {}
    constexpr BiCoef(int n) noexcept : fact_(n, 1), inv_(n, 1), finv_(n, 1) {
        init(n);
    }
    constexpr void init(int n) noexcept {
        fact_.assign(n, 1), inv_.assign(n, 1), finv_.assign(n, 1);
        int MOD = fact_[0].getmod();
        for(int i = 2; i < n; i++){
            fact_[i] = fact_[i-1] * i;
            inv_[i] = -inv_[MOD%i] * (MOD/i);
            finv_[i] = finv_[i-1] * inv_[i];
        }
    }
    constexpr T com(int n, int k) const noexcept {
        if (n < k || n < 0 || k < 0) return 0;
        return fact_[n] * finv_[k] * finv_[n-k];
    }
    constexpr T fact(int n) const noexcept {
        if (n < 0) return 0;
        return fact_[n];
    }
    constexpr T inv(int n) const noexcept {
        if (n < 0) return 0;
        return inv_[n];
    }
    constexpr T finv(int n) const noexcept {
        if (n < 0) return 0;
        return finv_[n];
    }
};

// Formal Power Series
template <typename mint> struct FPS : vector<mint> {
    using vector<mint>::vector;
 
    // constructor
    FPS(const vector<mint>& r) : vector<mint>(r) {}
 
    // core operator
    inline FPS pre(int siz) const {
        return FPS(begin(*this), begin(*this) + min((int)this->size(), siz));
    }
    inline FPS rev() const {
        FPS res = *this;
        reverse(begin(res), end(res));
        return res;
    }
    inline FPS& normalize() {
        while (!this->empty() && this->back() == 0) this->pop_back();
        return *this;
    }
 
    // basic operator
    inline FPS operator - () const noexcept {
        FPS res = (*this);
        for (int i = 0; i < (int)res.size(); ++i) res[i] = -res[i];
        return res;
    }
    inline FPS operator + (const mint& v) const { return FPS(*this) += v; }
    inline FPS operator + (const FPS& r) const { return FPS(*this) += r; }
    inline FPS operator - (const mint& v) const { return FPS(*this) -= v; }
    inline FPS operator - (const FPS& r) const { return FPS(*this) -= r; }
    inline FPS operator * (const mint& v) const { return FPS(*this) *= v; }
    inline FPS operator * (const FPS& r) const { return FPS(*this) *= r; }
    inline FPS operator / (const mint& v) const { return FPS(*this) /= v; }
    inline FPS operator / (const FPS& r) const { return FPS(*this) /= r; }
    inline FPS operator % (const FPS& r) const { return FPS(*this) %= r; }
    inline FPS operator << (int x) const { return FPS(*this) <<= x; }
    inline FPS operator >> (int x) const { return FPS(*this) >>= x; }
    inline FPS& operator += (const mint& v) {
        if (this->empty()) this->resize(1);
        (*this)[0] += v;
        return *this;
    }
    inline FPS& operator += (const FPS& r) {
        if (r.size() > this->size()) this->resize(r.size());
        for (int i = 0; i < (int)r.size(); ++i) (*this)[i] += r[i];
        return this->normalize();
    }
    inline FPS& operator -= (const mint& v) {
        if (this->empty()) this->resize(1);
        (*this)[0] -= v;
        return *this;
    }
    inline FPS& operator -= (const FPS& r) {
        if (r.size() > this->size()) this->resize(r.size());
        for (int i = 0; i < (int)r.size(); ++i) (*this)[i] -= r[i];
        return this->normalize();
    }
    inline FPS& operator *= (const mint& v) {
        for (int i = 0; i < (int)this->size(); ++i) (*this)[i] *= v;
        return *this;
    }
    inline FPS& operator *= (const FPS& r) {
        return *this = NTT::mul((*this), r);
    }
    inline FPS& operator /= (const mint& v) {
        assert(v != 0);
        mint iv = modinv(v);
        for (int i = 0; i < (int)this->size(); ++i) (*this)[i] *= iv;
        return *this;
    }
    inline FPS& operator /= (const FPS& r) {
        if (this->size() < r.size()) {
            this->clear();
            return *this;
        }
        int need = (int)this->size() - (int)r.size() + 1;
        *this = (this->rev() * inv(r.rev(), need)).pre(need).rev();
        //*this = (this->rev().pre(need) * inv(r.rev(), need)).pre(need).rev();
        return *this;
    }
    inline FPS& operator %= (const FPS &r) {
        FPS q = (*this) / r;
        return *this -= q * r;
    }
    inline FPS& operator <<= (int x) {
        FPS res(x, 0);
        res.insert(res.end(), begin(*this), end(*this));
        return *this = res;
    }
    inline FPS& operator >>= (int x) {
        FPS res;
        res.insert(res.end(), begin(*this) + x, end(*this));
        return *this = res;
    }
    inline mint eval(const mint& v){
        mint res = 0;
        for (int i = (int)this->size()-1; i >= 0; --i) {
            res *= v;
            res += (*this)[i];
        }
        return res;
    }
    inline friend FPS gcd(const FPS& f, const FPS& g) {
        if (g.empty()) return f;
        return gcd(g, f % g);
    }

    // advanced operation
    // df/dx
    inline friend FPS diff(const FPS& f) {
        int n = (int)f.size();
        FPS res(n-1);
        for (int i = 1; i < n; ++i) res[i-1] = f[i] * i;
        return res;
    }

    // \int f dx
    inline friend FPS integral(const FPS& f) {
        int n = (int)f.size();
        FPS res(n+1, 0);
        for (int i = 0; i < n; ++i) res[i+1] = f[i] / (i+1);
        return res;
    }

    // inv(f), f[0] must not be 0
    inline friend FPS inv(const FPS& f, int deg) {
        assert(f[0] != 0);
        if (deg < 0) deg = (int)f.size();
        FPS res({mint(1) / f[0]});
        for (int i = 1; i < deg; i <<= 1) {
            res = (res + res - res * res * f.pre(i << 1)).pre(i << 1);
        }
        return res.pre(deg);
    }
    inline friend FPS inv(const FPS& f) {
        return inv(f, f.size());
    }

    // log(f) = \int f'/f dx, f[0] must be 1
    inline friend FPS log(const FPS& f, int deg) {
        assert(f[0] == 1);
        FPS res = integral(diff(f) * inv(f, deg));
        res.resize(deg);
        return res;
    }
    inline friend FPS log(const FPS& f) {
        return log(f, f.size());
    }

    // exp(f), f[0] must be 0
    inline friend FPS exp(const FPS& f, int deg) {
        assert(f[0] == 0);
        FPS res(1, 1);
        for (int i = 1; i < deg; i <<= 1) {
            res = res * (f.pre(i<<1) - log(res, i<<1) + 1).pre(i<<1);
        }
        res.resize(deg);
        return res;
    }
    inline friend FPS exp(const FPS& f) {
        return exp(f, f.size());
    }

    // pow(f) = exp(e * log f)
    inline friend FPS pow(const FPS& f, long long e, int deg) {
        long long i = 0;
        while (i < (int)f.size() && f[i] == 0) ++i;
        if (i == (int)f.size()) return FPS(deg, 0);
        if (i * e >= deg) return FPS(deg, 0);
        mint k = f[i];
        FPS res = exp(log((f >> i) / k) * e) * modpow(k, e) << (e * i);
        res.resize(deg);
        return res;
    }
    inline friend FPS pow(const FPS& f, long long e) {
        return pow(f, e, f.size());
    }

    // sqrt(f), f[0] must be 1
    inline friend FPS sqrt(const FPS& f, int deg) {
        assert(f[0] == 1);
        int siz = 1;
        mint inv2 = mint(1) / 2;
        FPS res(1, 1);
        while (siz < deg) {
            siz <<= 1;
            FPS tmp(min(siz, (int)f.size()));
            for (int i = 0; i < (int)tmp.size(); ++i) tmp[i] = f[i];
            res += tmp * inv(f, siz);
            res.resize(siz);
            for (mint& x : res) res *= inv2;
        }
        return res;
    }
    inline friend FPS sqrt(const FPS& f) {
        return sqrt(f, f.size());
    }
};
using mint = Fp<>;

FPS<mint> modpow(const FPS<mint> &f, long long n, const FPS<mint> &m) {
    if (n == 0) return FPS<mint>(1, 1);
    auto t = modpow(f, n / 2, m);
    t = (t * t) % m;
    if (n & 1) t = (t * f) % m;
    auto q = t / m;
    auto r = t % m;
    return t;
}

int main() {
    long long N, P;
    while (cin >> N >> P) {
        if (N == 0) break;
        MODS[0] = P;
		
        FPS<mint> f(N+1);
        for (int i = 0; i < N+1; ++i) cin >> f[i];
        f.normalize();
        if (f.empty()) { 
            cout << P << endl;
            continue; 
        }
        
        FPS<mint> x(2, 0);
        x[1] = 1; // 多項式 x
        FPS<mint> g = modpow(x, P, f) - x;
        FPS<mint> res = gcd(f, g);
        cout << (int)res.size() - 1 << endl;
    }
}
accuracy: 1
time_ms: 70
memory_kb: 3616
final_rank: 11

code_snippet: //
// Formal Power Series (on runtime mod)
//
// verified:
//   Yosupo Judge
//     https://judge.yosupo.jp/problem/inv_of_formal_power_series
//
//   AOJ 2213 The Number of Solutions for a Polynomial
//     http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2213
//


#include <bits/stdc++.h>
using namespace std;

#define COUT(x) cout << #x << " = " << (x) << " (L" << __LINE__ << ")" << endl
template<class T1, class T2> ostream& operator << (ostream &s, pair<T1,T2> P)
{ return s << '<' << P.first << ", " << P.second << '>'; }
template<class T> ostream& operator << (ostream &s, vector<T> P)
{ for (int i = 0; i < P.size(); ++i) { if (i > 0) { s << " "; } s << P[i]; } return s; }
template<class T> ostream& operator << (ostream &s, vector<vector<T> > P)
{ for (int i = 0; i < P.size(); ++i) { s << endl << P[i]; } return s << endl; }
template<class T> ostream& operator << (ostream &s, set<T> P)
{ for(auto it : P) { s << "<" << it << "> "; } return s << endl; }
template<class T1, class T2> ostream& operator << (ostream &s, map<T1,T2> P)
{ for(auto it : P) { s << "<" << it.first << "->" << it.second << "> "; } return s << endl; }


// modint (replace MODS[0] on runtime)
vector<int> MODS = { 1000000007, 754974721, 167772161, 469762049 };
template<int IND = 0> struct Fp {
    long long val;
    constexpr Fp(long long v = 0) noexcept : val(v % MODS[IND]) {
        if (val < 0) val += MODS[IND];
    }
    constexpr int getmod() const { return MODS[IND]; }
    constexpr Fp operator - () const noexcept {
        return val ? MODS[IND] - val : 0;
    }
    constexpr Fp operator + (const Fp& r) const noexcept { return Fp(*this) += r; }
    constexpr Fp operator - (const Fp& r) const noexcept { return Fp(*this) -= r; }
    constexpr Fp operator * (const Fp& r) const noexcept { return Fp(*this) *= r; }
    constexpr Fp operator / (const Fp& r) const noexcept { return Fp(*this) /= r; }
    constexpr Fp& operator += (const Fp& r) noexcept {
        val += r.val;
        if (val >= MODS[IND]) val -= MODS[IND];
        return *this;
    }
    constexpr Fp& operator -= (const Fp& r) noexcept {
        val -= r.val;
        if (val < 0) val += MODS[IND];
        return *this;
    }
    constexpr Fp& operator *= (const Fp& r) noexcept {
        val = val * r.val % MODS[IND];
        return *this;
    }
    constexpr Fp& operator /= (const Fp& r) noexcept {
        long long a = r.val, b = MODS[IND], u = 1, v = 0;
        while (b) {
            long long t = a / b;
            a -= t * b; swap(a, b);
            u -= t * v; swap(u, v);
        }
        val = val * u % MODS[IND];
        if (val < 0) val += MODS[IND];
        return *this;
    }
    constexpr bool operator == (const Fp& r) const noexcept {
        return this->val == r.val;
    }
    constexpr bool operator != (const Fp& r) const noexcept {
        return this->val != r.val;
    }
    friend constexpr istream& operator >> (istream& is, Fp<IND>& x) noexcept {
        is >> x.val;
        x.val %= MODS[IND];
        if (x.val < 0) x.val += MODS[IND];
        return is;
    }
    friend constexpr ostream& operator << (ostream& os, const Fp<IND>& x) noexcept {
        return os << x.val;
    }
    friend constexpr Fp<IND> modpow(const Fp<IND>& r, long long n) noexcept {
        if (n == 0) return 1;
        auto t = modpow(r, n / 2);
        t = t * t;
        if (n & 1) t = t * r;
        return t;
    }
    friend constexpr Fp<IND> modinv(const Fp<IND>& r) noexcept {
        long long a = r.val, b = MODS[IND], u = 1, v = 0;
        while (b) {
            long long t = a / b;
            a -= t * b, swap(a, b);
            u -= t * v, swap(u, v);
        }
        return Fp<IND>(u);
    }
};

namespace NTT {    
    long long modpow(long long a, long long n, int mod) {
        long long res = 1;
        while (n > 0) {
            if (n & 1) res = res * a % mod;
            a = a * a % mod;
            n >>= 1;
        }
        return res;
    }

    long long modinv(long long a, int mod) {
        long long b = mod, u = 1, v = 0;
        while (b) {
            long long t = a / b;
            a -= t * b, swap(a, b);
            u -= t * v, swap(u, v);
        }
        u %= mod;
        if (u < 0) u += mod;
        return u;
    }

    int calc_primitive_root(int mod) {
        if (mod == 2) return 1;
        if (mod == 167772161) return 3;
        if (mod == 469762049) return 3;
        if (mod == 754974721) return 11;
        if (mod == 998244353) return 3;
        int divs[20] = {};
        divs[0] = 2;
        int cnt = 1;
        long long x = (mod - 1) / 2;
        while (x % 2 == 0) x /= 2;
        for (long long i = 3; i * i <= x; i += 2) {
            if (x % i == 0) {
                divs[cnt++] = i;
                while (x % i == 0) x /= i;
            }
        }
        if (x > 1) divs[cnt++] = x;
        for (int g = 2;; g++) {
            bool ok = true;
            for (int i = 0; i < cnt; i++) {
                if (modpow(g, (mod - 1) / divs[i], mod) == 1) {
                    ok = false;
                    break;
                }
            }
            if (ok) return g;
        }
    }

    int get_fft_size(int N, int M) {
        int size_a = 1, size_b = 1;
        while (size_a < N) size_a <<= 1;
        while (size_b < M) size_b <<= 1;
        return max(size_a, size_b) << 1;
    }

    // number-theoretic transform
    set<int> setmod;
    template<class mint> void trans(vector<mint>& v, bool inv = false) {
        if (v.empty()) return;
        int N = (int)v.size();
        int MOD = v[0].getmod();
        int PR = calc_primitive_root(MOD);
        static vector<long long> vbw(30), vibw(30);
        if (!setmod.count(MOD)) {
            setmod.insert(MOD);
            for (int k = 0; k < 30; ++k) {
                vbw[k] = modpow(PR, (MOD - 1) >> (k + 1), MOD);
                vibw[k] = modinv(vbw[k], MOD);
            }
        }
        for (int i = 0, j = 1; j < N - 1; j++) {
            for (int k = N >> 1; k > (i ^= k); k >>= 1);
            if (i > j) swap(v[i], v[j]);
        }
        for (int k = 0, t = 2; t <= N; ++k, t <<= 1) {
            long long bw = vbw[k];
            if (inv) bw = vibw[k];
            for (int i = 0; i < N; i += t) {
                mint w = 1;
                for (int j = 0; j < t/2; ++j) {
                    int j1 = i + j, j2 = i + j + t/2;
                    mint c1 = v[j1], c2 = v[j2] * w;
                    v[j1] = c1 + c2;
                    v[j2] = c1 - c2;
                    w *= bw;
                }
            }
        }
        if (inv) {
            long long invN = modinv(N, MOD);
            for (int i = 0; i < N; ++i) v[i] = v[i] * invN;
        }
    }

    // for garner
    static constexpr int IND1 = 1; //754974721;
    static constexpr int IND2 = 2; //167772161;
    static constexpr int IND3 = 3; //469762049;
    using mint1 = Fp<IND1>;
    using mint2 = Fp<IND2>;
    using mint3 = Fp<IND3>;
    static const mint2 imod1 = 95869806; // modinv(MOD1, MOD2);
    static const mint3 imod2 = 104391568; // modinv(MOD2, MOD3);
    static const mint3 imod12 = 187290749; // imod2 / MOD1;

    // small case (T = mint, long long)
    template<class T> vector<T> naive_mul 
    (const vector<T>& A, const vector<T>& B) {
        if (A.empty() || B.empty()) return {};
        int N = (int)A.size(), M = (int)B.size();
        vector<T> res(N + M - 1);
        for (int i = 0; i < N; ++i)
            for (int j = 0; j < M; ++j)
                res[i + j] += A[i] * B[j];
        return res;
    }

    // mint
    template<class mint> vector<mint> mul
    (const vector<mint>& A, const vector<mint>& B) {
        if (A.empty() || B.empty()) return {};
        int N = (int)A.size(), M = (int)B.size();
        if (min(N, M) < 50) return naive_mul(A, B);
        int MOD = A[0].getmod();
        int size_fft = get_fft_size(N, M);
        if (MOD == 998244353) {
            vector<mint> a(size_fft), b(size_fft), c(size_fft);
            for (int i = 0; i < N; ++i) a[i] = A[i];
            for (int i = 0; i < M; ++i) b[i] = B[i];
            trans(a), trans(b);
            vector<mint> res(size_fft);
            for (int i = 0; i < size_fft; ++i) res[i] = a[i] * b[i];
            trans(res, true);
            res.resize(N + M - 1);
            return res;
        }
        vector<mint1> a1(size_fft, 0), b1(size_fft, 0), c1(size_fft, 0);
        vector<mint2> a2(size_fft, 0), b2(size_fft, 0), c2(size_fft, 0);
        vector<mint3> a3(size_fft, 0), b3(size_fft, 0), c3(size_fft, 0);
        for (int i = 0; i < N; ++i)
            a1[i] = A[i].val, a2[i] = A[i].val, a3[i] = A[i].val;
        for (int i = 0; i < M; ++i)
            b1[i] = B[i].val, b2[i] = B[i].val, b3[i] = B[i].val;
        trans(a1), trans(a2), trans(a3), trans(b1), trans(b2), trans(b3);
        for (int i = 0; i < size_fft; ++i) {
            c1[i] = a1[i] * b1[i];
            c2[i] = a2[i] * b2[i];
            c3[i] = a3[i] * b3[i];
        }
        trans(c1, true), trans(c2, true), trans(c3, true);
        mint mod1 = MODS[IND1], mod12 = mod1 * MODS[IND2];
        vector<mint> res(N + M - 1);
        for (int i = 0; i < N + M - 1; ++i) {
            int y1 = c1[i].val;
            int y2 = (imod1 * (c2[i] - y1)).val;
            int y3 = (imod12 * (c3[i] - y1) - imod2 * y2).val;
            res[i] = mod12 * y3 + mod1 * y2 + y1;
        }
        return res;
    }
};

// Binomial Coefficient
template<class T> struct BiCoef {
    vector<T> fact_, inv_, finv_;
    constexpr BiCoef() {}
    constexpr BiCoef(int n) noexcept : fact_(n, 1), inv_(n, 1), finv_(n, 1) {
        init(n);
    }
    constexpr void init(int n) noexcept {
        fact_.assign(n, 1), inv_.assign(n, 1), finv_.assign(n, 1);
        int MOD = fact_[0].getmod();
        for(int i = 2; i < n; i++){
            fact_[i] = fact_[i-1] * i;
            inv_[i] = -inv_[MOD%i] * (MOD/i);
            finv_[i] = finv_[i-1] * inv_[i];
        }
    }
    constexpr T com(int n, int k) const noexcept {
        if (n < k || n < 0 || k < 0) return 0;
        return fact_[n] * finv_[k] * finv_[n-k];
    }
    constexpr T fact(int n) const noexcept {
        if (n < 0) return 0;
        return fact_[n];
    }
    constexpr T inv(int n) const noexcept {
        if (n < 0) return 0;
        return inv_[n];
    }
    constexpr T finv(int n) const noexcept {
        if (n < 0) return 0;
        return finv_[n];
    }
};

// Formal Power Series
template <typename mint> struct FPS : vector<mint> {
    using vector<mint>::vector;
 
    // constructor
    FPS(const vector<mint>& r) : vector<mint>(r) {}
 
    // core operator
    inline FPS pre(int siz) const {
        return FPS(begin(*this), begin(*this) + min((int)this->size(), siz));
    }
    inline FPS rev() const {
        FPS res = *this;
        reverse(begin(res), end(res));
        return res;
    }
    inline FPS& normalize() {
        while (!this->empty() && this->back() == 0) this->pop_back();
        return *this;
    }
 
    // basic operator
    inline FPS operator - () const noexcept {
        FPS res = (*this);
        for (int i = 0; i < (int)res.size(); ++i) res[i] = -res[i];
        return res;
    }
    inline FPS operator + (const mint& v) const { return FPS(*this) += v; }
    inline FPS operator + (const FPS& r) const { return FPS(*this) += r; }
    inline FPS operator - (const mint& v) const { return FPS(*this) -= v; }
    inline FPS operator - (const FPS& r) const { return FPS(*this) -= r; }
    inline FPS operator * (const mint& v) const { return FPS(*this) *= v; }
    inline FPS operator * (const FPS& r) const { return FPS(*this) *= r; }
    inline FPS operator / (const mint& v) const { return FPS(*this) /= v; }
    inline FPS operator / (const FPS& r) const { return FPS(*this) /= r; }
    inline FPS operator % (const FPS& r) const { return FPS(*this) %= r; }
    inline FPS operator << (int x) const { return FPS(*this) <<= x; }
    inline FPS operator >> (int x) const { return FPS(*this) >>= x; }
    inline FPS& operator += (const mint& v) {
        if (this->empty()) this->resize(1);
        (*this)[0] += v;
        return *this;
    }
    inline FPS& operator += (const FPS& r) {
        if (r.size() > this->size()) this->resize(r.size());
        for (int i = 0; i < (int)r.size(); ++i) (*this)[i] += r[i];
        return this->normalize();
    }
    inline FPS& operator -= (const mint& v) {
        if (this->empty()) this->resize(1);
        (*this)[0] -= v;
        return *this;
    }
    inline FPS& operator -= (const FPS& r) {
        if (r.size() > this->size()) this->resize(r.size());
        for (int i = 0; i < (int)r.size(); ++i) (*this)[i] -= r[i];
        return this->normalize();
    }
    inline FPS& operator *= (const mint& v) {
        for (int i = 0; i < (int)this->size(); ++i) (*this)[i] *= v;
        return *this;
    }
    inline FPS& operator *= (const FPS& r) {
        return *this = NTT::mul((*this), r);
    }
    inline FPS& operator /= (const mint& v) {
        assert(v != 0);
        mint iv = modinv(v);
        for (int i = 0; i < (int)this->size(); ++i) (*this)[i] *= iv;
        return *this;
    }
    inline FPS& operator /= (const FPS& r) {
        if (this->size() < r.size()) {
            this->clear();
            return *this;
        }
        int need = (int)this->size() - (int)r.size() + 1;
        *this = (this->rev() * inv(r.rev(), need)).pre(need).rev();
        //*this = (this->rev().pre(need) * inv(r.rev(), need)).pre(need).rev();
        return *this;
    }
    inline FPS& operator %= (const FPS &r) {
        FPS q = (*this) / r;
        return *this -= q * r;
    }
    inline FPS& operator <<= (int x) {
        FPS res(x, 0);
        res.insert(res.end(), begin(*this), end(*this));
        return *this = res;
    }
    inline FPS& operator >>= (int x) {
        FPS res;
        res.insert(res.end(), begin(*this) + x, end(*this));
        return *this = res;
    }
    inline mint eval(const mint& v){
        mint res = 0;
        for (int i = (int)this->size()-1; i >= 0; --i) {
            res *= v;
            res += (*this)[i];
        }
        return res;
    }
    inline friend FPS gcd(const FPS& f, const FPS& g) {
        if (g.empty()) return f;
        return gcd(g, f % g);
    }

    // advanced operation
    // df/dx
    inline friend FPS diff(const FPS& f) {
        int n = (int)f.size();
        FPS res(n-1);
        for (int i = 1; i < n; ++i) res[i-1] = f[i] * i;
        return res;
    }

    // \int f dx
    inline friend FPS integral(const FPS& f) {
        int n = (int)f.size();
        FPS res(n+1, 0);
        for (int i = 0; i < n; ++i) res[i+1] = f[i] / (i+1);
        return res;
    }

    // inv(f), f[0] must not be 0
    inline friend FPS inv(const FPS& f, int deg) {
        assert(f[0] != 0);
        if (deg < 0) deg = (int)f.size();
        FPS res({mint(1) / f[0]});
        for (int i = 1; i < deg; i <<= 1) {
            res = (res + res - res * res * f.pre(i << 1)).pre(i << 1);
        }
        return res.pre(deg);
    }
    inline friend FPS inv(const FPS& f) {
        return inv(f, f.size());
    }

    // log(f) = \int f'/f dx, f[0] must be 1
    inline friend FPS log(const FPS& f, int deg) {
        assert(f[0] == 1);
        FPS res = integral(diff(f) * inv(f, deg));
        res.resize(deg);
        return res;
    }
    inline friend FPS log(const FPS& f) {
        return log(f, f.size());
    }

    // exp(f), f[0] must be 0
    inline friend FPS exp(const FPS& f, int deg) {
        assert(f[0] == 0);
        FPS res(1, 1);
        for (int i = 1; i < deg; i <<= 1) {
            res = res * (f.pre(i<<1) - log(res, i<<1) + 1).pre(i<<1);
        }
        res.resize(deg);
        return res;
    }
    inline friend FPS exp(const FPS& f) {
        return exp(f, f.size());
    }

    // pow(f) = exp(e * log f)
    inline friend FPS pow(const FPS& f, long long e, int deg) {
        long long i = 0;
        while (i < (int)f.size() && f[i] == 0) ++i;
        if (i == (int)f.size()) return FPS(deg, 0);
        if (i * e >= deg) return FPS(deg, 0);
        mint k = f[i];
        FPS res = exp(log((f >> i) / k) * e) * modpow(k, e) << (e * i);
        res.resize(deg);
        return res;
    }
    inline friend FPS pow(const FPS& f, long long e) {
        return pow(f, e, f.size());
    }

    // sqrt(f), f[0] must be 1
    inline friend FPS sqrt(const FPS& f, int deg) {
        assert(f[0] == 1);
        int siz = 1;
        mint inv2 = mint(1) / 2;
        FPS res(1, 1);
        while (siz < deg) {
            siz <<= 1;
            FPS tmp(min(siz, (int)f.size()));
            for (int i = 0; i < (int)tmp.size(); ++i) tmp[i] = f[i];
            res += tmp * inv(f, siz);
            res.resize(siz);
            for (mint& x : res) res *= inv2;
        }
        return res;
    }
    inline friend FPS sqrt(const FPS& f) {
        return sqrt(f, f.size());
    }
};
using mint = Fp<>;

FPS<mint> modpow(const FPS<mint> &f, long long n, const FPS<mint> &m) {
    if (n == 0) return FPS<mint>(1, 1);
    auto t = modpow(f, n / 2, m);
    t = (t * t) % m;
    if (n & 1) t = (t * f) % m;
    auto q = t / m;
    auto r = t % m;
    return t;
}

int main() {
    long long N, P;
    while (cin >> N >> P) {
        if (N == 0) break;
        MODS[0] = P;
		
        FPS<mint> f(N+1);
        for (int i = 0; i < N+1; ++i) cin >> f[i];
        f.normalize();
        if (f.empty()) { 
            cout << P << endl;
            continue; 
        }
        
        FPS<mint> x(2, 0);
        x[1] = 1; // 多項式 x
        FPS<mint> g = modpow(x, P, f) - x;
        FPS<mint> res = gcd(f, g);
        cout << (int)res.size() - 1 << endl;
    }
}
accuracy: 1
time_ms: 90
memory_kb: 3488
final_rank: 12

code_snippet: //
// Formal Power Series (on runtime mod)
//
// verified:
//   Yosupo Judge
//     https://judge.yosupo.jp/problem/inv_of_formal_power_series
//
//   AOJ 2213 The Number of Solutions for a Polynomial
//     http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2213
//


#include <bits/stdc++.h>
using namespace std;

#define COUT(x) cout << #x << " = " << (x) << " (L" << __LINE__ << ")" << endl
template<class T1, class T2> ostream& operator << (ostream &s, pair<T1,T2> P)
{ return s << '<' << P.first << ", " << P.second << '>'; }
template<class T> ostream& operator << (ostream &s, vector<T> P)
{ for (int i = 0; i < P.size(); ++i) { if (i > 0) { s << " "; } s << P[i]; } return s; }
template<class T> ostream& operator << (ostream &s, vector<vector<T> > P)
{ for (int i = 0; i < P.size(); ++i) { s << endl << P[i]; } return s << endl; }
template<class T> ostream& operator << (ostream &s, set<T> P)
{ for(auto it : P) { s << "<" << it << "> "; } return s << endl; }
template<class T1, class T2> ostream& operator << (ostream &s, map<T1,T2> P)
{ for(auto it : P) { s << "<" << it.first << "->" << it.second << "> "; } return s << endl; }


// modint (replace MODS[0] on runtime)
vector<int> MODS = { 1000000007, 754974721, 167772161, 469762049 };
template<int IND = 0> struct Fp {
    long long val;
    constexpr Fp(long long v = 0) noexcept : val(v % MODS[IND]) {
        if (val < 0) val += MODS[IND];
    }
    constexpr int getmod() const { return MODS[IND]; }
    constexpr Fp operator - () const noexcept {
        return val ? MODS[IND] - val : 0;
    }
    constexpr Fp operator + (const Fp& r) const noexcept { return Fp(*this) += r; }
    constexpr Fp operator - (const Fp& r) const noexcept { return Fp(*this) -= r; }
    constexpr Fp operator * (const Fp& r) const noexcept { return Fp(*this) *= r; }
    constexpr Fp operator / (const Fp& r) const noexcept { return Fp(*this) /= r; }
    constexpr Fp& operator += (const Fp& r) noexcept {
        val += r.val;
        if (val >= MODS[IND]) val -= MODS[IND];
        return *this;
    }
    constexpr Fp& operator -= (const Fp& r) noexcept {
        val -= r.val;
        if (val < 0) val += MODS[IND];
        return *this;
    }
    constexpr Fp& operator *= (const Fp& r) noexcept {
        val = val * r.val % MODS[IND];
        return *this;
    }
    constexpr Fp& operator /= (const Fp& r) noexcept {
        long long a = r.val, b = MODS[IND], u = 1, v = 0;
        while (b) {
            long long t = a / b;
            a -= t * b; swap(a, b);
            u -= t * v; swap(u, v);
        }
        val = val * u % MODS[IND];
        if (val < 0) val += MODS[IND];
        return *this;
    }
    constexpr bool operator == (const Fp& r) const noexcept {
        return this->val == r.val;
    }
    constexpr bool operator != (const Fp& r) const noexcept {
        return this->val != r.val;
    }
    friend constexpr istream& operator >> (istream& is, Fp<IND>& x) noexcept {
        is >> x.val;
        x.val %= MODS[IND];
        if (x.val < 0) x.val += MODS[IND];
        return is;
    }
    friend constexpr ostream& operator << (ostream& os, const Fp<IND>& x) noexcept {
        return os << x.val;
    }
    friend constexpr Fp<IND> modpow(const Fp<IND>& r, long long n) noexcept {
        if (n == 0) return 1;
        auto t = modpow(r, n / 2);
        t = t * t;
        if (n & 1) t = t * r;
        return t;
    }
    friend constexpr Fp<IND> modinv(const Fp<IND>& r) noexcept {
        long long a = r.val, b = MODS[IND], u = 1, v = 0;
        while (b) {
            long long t = a / b;
            a -= t * b, swap(a, b);
            u -= t * v, swap(u, v);
        }
        return Fp<IND>(u);
    }
};

namespace NTT {    
    long long modpow(long long a, long long n, int mod) {
        long long res = 1;
        while (n > 0) {
            if (n & 1) res = res * a % mod;
            a = a * a % mod;
            n >>= 1;
        }
        return res;
    }

    long long modinv(long long a, int mod) {
        long long b = mod, u = 1, v = 0;
        while (b) {
            long long t = a / b;
            a -= t * b, swap(a, b);
            u -= t * v, swap(u, v);
        }
        u %= mod;
        if (u < 0) u += mod;
        return u;
    }

    int calc_primitive_root(int mod) {
        if (mod == 2) return 1;
        if (mod == 167772161) return 3;
        if (mod == 469762049) return 3;
        if (mod == 754974721) return 11;
        if (mod == 998244353) return 3;
        int divs[20] = {};
        divs[0] = 2;
        int cnt = 1;
        long long x = (mod - 1) / 2;
        while (x % 2 == 0) x /= 2;
        for (long long i = 3; i * i <= x; i += 2) {
            if (x % i == 0) {
                divs[cnt++] = i;
                while (x % i == 0) x /= i;
            }
        }
        if (x > 1) divs[cnt++] = x;
        for (int g = 2;; g++) {
            bool ok = true;
            for (int i = 0; i < cnt; i++) {
                if (modpow(g, (mod - 1) / divs[i], mod) == 1) {
                    ok = false;
                    break;
                }
            }
            if (ok) return g;
        }
    }

    int get_fft_size(int N, int M) {
        int size_a = 1, size_b = 1;
        while (size_a < N) size_a <<= 1;
        while (size_b < M) size_b <<= 1;
        return max(size_a, size_b) << 1;
    }

    // number-theoretic transform
    set<int> setmod;
    template<class mint> void trans(vector<mint>& v, bool inv = false) {
        if (v.empty()) return;
        int N = (int)v.size();
        int MOD = v[0].getmod();
        int PR = calc_primitive_root(MOD);
        static vector<long long> vbw(30), vibw(30);
        if (!setmod.count(MOD)) {
            setmod.insert(MOD);
            for (int k = 0; k < 30; ++k) {
                vbw[k] = modpow(PR, (MOD - 1) >> (k + 1), MOD);
                vibw[k] = modinv(vbw[k], MOD);
            }
        }
        for (int i = 0, j = 1; j < N - 1; j++) {
            for (int k = N >> 1; k > (i ^= k); k >>= 1);
            if (i > j) swap(v[i], v[j]);
        }
        for (int k = 0, t = 2; t <= N; ++k, t <<= 1) {
            long long bw = vbw[k];
            if (inv) bw = vibw[k];
            for (int i = 0; i < N; i += t) {
                mint w = 1;
                for (int j = 0; j < t/2; ++j) {
                    int j1 = i + j, j2 = i + j + t/2;
                    mint c1 = v[j1], c2 = v[j2] * w;
                    v[j1] = c1 + c2;
                    v[j2] = c1 - c2;
                    w *= bw;
                }
            }
        }
        if (inv) {
            long long invN = modinv(N, MOD);
            for (int i = 0; i < N; ++i) v[i] = v[i] * invN;
        }
    }

    // for garner
    static constexpr int IND1 = 1; //754974721;
    static constexpr int IND2 = 2; //167772161;
    static constexpr int IND3 = 3; //469762049;
    using mint1 = Fp<IND1>;
    using mint2 = Fp<IND2>;
    using mint3 = Fp<IND3>;
    static const mint2 imod1 = 95869806; // modinv(MOD1, MOD2);
    static const mint3 imod2 = 104391568; // modinv(MOD2, MOD3);
    static const mint3 imod12 = 187290749; // imod2 / MOD1;

    // small case (T = mint, long long)
    template<class T> vector<T> naive_mul 
    (const vector<T>& A, const vector<T>& B) {
        if (A.empty() || B.empty()) return {};
        int N = (int)A.size(), M = (int)B.size();
        vector<T> res(N + M - 1);
        for (int i = 0; i < N; ++i)
            for (int j = 0; j < M; ++j)
                res[i + j] += A[i] * B[j];
        return res;
    }

    // mint
    template<class mint> vector<mint> mul
    (const vector<mint>& A, const vector<mint>& B) {
        if (A.empty() || B.empty()) return {};
        int N = (int)A.size(), M = (int)B.size();
        if (min(N, M) < 2) return naive_mul(A, B);
        int MOD = A[0].getmod();
        int size_fft = get_fft_size(N, M);
        if (MOD == 998244353) {
            vector<mint> a(size_fft), b(size_fft), c(size_fft);
            for (int i = 0; i < N; ++i) a[i] = A[i];
            for (int i = 0; i < M; ++i) b[i] = B[i];
            trans(a), trans(b);
            vector<mint> res(size_fft);
            for (int i = 0; i < size_fft; ++i) res[i] = a[i] * b[i];
            trans(res, true);
            res.resize(N + M - 1);
            return res;
        }
        vector<mint1> a1(size_fft, 0), b1(size_fft, 0), c1(size_fft, 0);
        vector<mint2> a2(size_fft, 0), b2(size_fft, 0), c2(size_fft, 0);
        vector<mint3> a3(size_fft, 0), b3(size_fft, 0), c3(size_fft, 0);
        for (int i = 0; i < N; ++i)
            a1[i] = A[i].val, a2[i] = A[i].val, a3[i] = A[i].val;
        for (int i = 0; i < M; ++i)
            b1[i] = B[i].val, b2[i] = B[i].val, b3[i] = B[i].val;
        trans(a1), trans(a2), trans(a3), trans(b1), trans(b2), trans(b3);
        for (int i = 0; i < size_fft; ++i) {
            c1[i] = a1[i] * b1[i];
            c2[i] = a2[i] * b2[i];
            c3[i] = a3[i] * b3[i];
        }
        trans(c1, true), trans(c2, true), trans(c3, true);
        mint mod1 = MODS[IND1], mod12 = mod1 * MODS[IND2];
        vector<mint> res(N + M - 1);
        for (int i = 0; i < N + M - 1; ++i) {
            int y1 = c1[i].val;
            int y2 = (imod1 * (c2[i] - y1)).val;
            int y3 = (imod12 * (c3[i] - y1) - imod2 * y2).val;
            res[i] = mod12 * y3 + mod1 * y2 + y1;
        }
        return res;
    }
};

// Binomial Coefficient
template<class T> struct BiCoef {
    vector<T> fact_, inv_, finv_;
    constexpr BiCoef() {}
    constexpr BiCoef(int n) noexcept : fact_(n, 1), inv_(n, 1), finv_(n, 1) {
        init(n);
    }
    constexpr void init(int n) noexcept {
        fact_.assign(n, 1), inv_.assign(n, 1), finv_.assign(n, 1);
        int MOD = fact_[0].getmod();
        for(int i = 2; i < n; i++){
            fact_[i] = fact_[i-1] * i;
            inv_[i] = -inv_[MOD%i] * (MOD/i);
            finv_[i] = finv_[i-1] * inv_[i];
        }
    }
    constexpr T com(int n, int k) const noexcept {
        if (n < k || n < 0 || k < 0) return 0;
        return fact_[n] * finv_[k] * finv_[n-k];
    }
    constexpr T fact(int n) const noexcept {
        if (n < 0) return 0;
        return fact_[n];
    }
    constexpr T inv(int n) const noexcept {
        if (n < 0) return 0;
        return inv_[n];
    }
    constexpr T finv(int n) const noexcept {
        if (n < 0) return 0;
        return finv_[n];
    }
};

// Formal Power Series
template <typename mint> struct FPS : vector<mint> {
    using vector<mint>::vector;
 
    // constructor
    FPS(const vector<mint>& r) : vector<mint>(r) {}
 
    // core operator
    inline FPS pre(int siz) const {
        return FPS(begin(*this), begin(*this) + min((int)this->size(), siz));
    }
    inline FPS rev() const {
        FPS res = *this;
        reverse(begin(res), end(res));
        return res;
    }
    inline FPS& normalize() {
        while (!this->empty() && this->back() == 0) this->pop_back();
        return *this;
    }
 
    // basic operator
    inline FPS operator - () const noexcept {
        FPS res = (*this);
        for (int i = 0; i < (int)res.size(); ++i) res[i] = -res[i];
        return res;
    }
    inline FPS operator + (const mint& v) const { return FPS(*this) += v; }
    inline FPS operator + (const FPS& r) const { return FPS(*this) += r; }
    inline FPS operator - (const mint& v) const { return FPS(*this) -= v; }
    inline FPS operator - (const FPS& r) const { return FPS(*this) -= r; }
    inline FPS operator * (const mint& v) const { return FPS(*this) *= v; }
    inline FPS operator * (const FPS& r) const { return FPS(*this) *= r; }
    inline FPS operator / (const mint& v) const { return FPS(*this) /= v; }
    inline FPS operator / (const FPS& r) const { return FPS(*this) /= r; }
    inline FPS operator % (const FPS& r) const { return FPS(*this) %= r; }
    inline FPS operator << (int x) const { return FPS(*this) <<= x; }
    inline FPS operator >> (int x) const { return FPS(*this) >>= x; }
    inline FPS& operator += (const mint& v) {
        if (this->empty()) this->resize(1);
        (*this)[0] += v;
        return *this;
    }
    inline FPS& operator += (const FPS& r) {
        if (r.size() > this->size()) this->resize(r.size());
        for (int i = 0; i < (int)r.size(); ++i) (*this)[i] += r[i];
        return this->normalize();
    }
    inline FPS& operator -= (const mint& v) {
        if (this->empty()) this->resize(1);
        (*this)[0] -= v;
        return *this;
    }
    inline FPS& operator -= (const FPS& r) {
        if (r.size() > this->size()) this->resize(r.size());
        for (int i = 0; i < (int)r.size(); ++i) (*this)[i] -= r[i];
        return this->normalize();
    }
    inline FPS& operator *= (const mint& v) {
        for (int i = 0; i < (int)this->size(); ++i) (*this)[i] *= v;
        return *this;
    }
    inline FPS& operator *= (const FPS& r) {
        return *this = NTT::mul((*this), r);
    }
    inline FPS& operator /= (const mint& v) {
        assert(v != 0);
        mint iv = modinv(v);
        for (int i = 0; i < (int)this->size(); ++i) (*this)[i] *= iv;
        return *this;
    }
    inline FPS& operator /= (const FPS& r) {
        if (this->size() < r.size()) {
            this->clear();
            return *this;
        }
        int need = (int)this->size() - (int)r.size() + 1;
        *this = (this->rev() * inv(r.rev(), need)).pre(need).rev();
        //*this = (this->rev().pre(need) * inv(r.rev(), need)).pre(need).rev();
        return *this;
    }
    inline FPS& operator %= (const FPS &r) {
        FPS q = (*this) / r;
        return *this -= q * r;
    }
    inline FPS& operator <<= (int x) {
        FPS res(x, 0);
        res.insert(res.end(), begin(*this), end(*this));
        return *this = res;
    }
    inline FPS& operator >>= (int x) {
        FPS res;
        res.insert(res.end(), begin(*this) + x, end(*this));
        return *this = res;
    }
    inline mint eval(const mint& v){
        mint res = 0;
        for (int i = (int)this->size()-1; i >= 0; --i) {
            res *= v;
            res += (*this)[i];
        }
        return res;
    }
    inline friend FPS gcd(const FPS& f, const FPS& g) {
        if (g.empty()) return f;
        return gcd(g, f % g);
    }

    // advanced operation
    // df/dx
    inline friend FPS diff(const FPS& f) {
        int n = (int)f.size();
        FPS res(n-1);
        for (int i = 1; i < n; ++i) res[i-1] = f[i] * i;
        return res;
    }

    // \int f dx
    inline friend FPS integral(const FPS& f) {
        int n = (int)f.size();
        FPS res(n+1, 0);
        for (int i = 0; i < n; ++i) res[i+1] = f[i] / (i+1);
        return res;
    }

    // inv(f), f[0] must not be 0
    inline friend FPS inv(const FPS& f, int deg) {
        assert(f[0] != 0);
        if (deg < 0) deg = (int)f.size();
        FPS res({mint(1) / f[0]});
        for (int i = 1; i < deg; i <<= 1) {
            res = (res + res - res * res * f.pre(i << 1)).pre(i << 1);
        }
        return res.pre(deg);
    }
    inline friend FPS inv(const FPS& f) {
        return inv(f, f.size());
    }

    // log(f) = \int f'/f dx, f[0] must be 1
    inline friend FPS log(const FPS& f, int deg) {
        assert(f[0] == 1);
        FPS res = integral(diff(f) * inv(f, deg));
        res.resize(deg);
        return res;
    }
    inline friend FPS log(const FPS& f) {
        return log(f, f.size());
    }

    // exp(f), f[0] must be 0
    inline friend FPS exp(const FPS& f, int deg) {
        assert(f[0] == 0);
        FPS res(1, 1);
        for (int i = 1; i < deg; i <<= 1) {
            res = res * (f.pre(i<<1) - log(res, i<<1) + 1).pre(i<<1);
        }
        res.resize(deg);
        return res;
    }
    inline friend FPS exp(const FPS& f) {
        return exp(f, f.size());
    }

    // pow(f) = exp(e * log f)
    inline friend FPS pow(const FPS& f, long long e, int deg) {
        long long i = 0;
        while (i < (int)f.size() && f[i] == 0) ++i;
        if (i == (int)f.size()) return FPS(deg, 0);
        if (i * e >= deg) return FPS(deg, 0);
        mint k = f[i];
        FPS res = exp(log((f >> i) / k) * e) * modpow(k, e) << (e * i);
        res.resize(deg);
        return res;
    }
    inline friend FPS pow(const FPS& f, long long e) {
        return pow(f, e, f.size());
    }

    // sqrt(f), f[0] must be 1
    inline friend FPS sqrt(const FPS& f, int deg) {
        assert(f[0] == 1);
        int siz = 1;
        mint inv2 = mint(1) / 2;
        FPS res(1, 1);
        while (siz < deg) {
            siz <<= 1;
            FPS tmp(min(siz, (int)f.size()));
            for (int i = 0; i < (int)tmp.size(); ++i) tmp[i] = f[i];
            res += tmp * inv(f, siz);
            res.resize(siz);
            for (mint& x : res) res *= inv2;
        }
        return res;
    }
    inline friend FPS sqrt(const FPS& f) {
        return sqrt(f, f.size());
    }
};
using mint = Fp<>;

FPS<mint> modpow(const FPS<mint> &f, long long n, const FPS<mint> &m) {
    if (n == 0) return FPS<mint>(1, 1);
    auto t = modpow(f, n / 2, m);
    t = (t * t) % m;
    if (n & 1) t = (t * f) % m;
    auto q = t / m;
    auto r = t % m;
    return t;
}

int main() {
    /*
    MODS[0] = 1000000007;
    FPS<mint> x = {1, 2, 3, 2, 8, 32, 4, 42, 42, 42, 42};
    FPS<mint> y = {1, 5, 1, 2, 42};
    FPS<mint> q = x / y;
    FPS<mint> r = x % y;
    COUT(q);
    COUT(r);
    COUT(y * q + r);
    COUT(x * y);
    */

    long long N, P;
    while (cin >> N >> P) {
        if (N == 0) break;
        MODS[0] = P;
		
        FPS<mint> f(N+1);
        for (int i = 0; i < N+1; ++i) cin >> f[i];
        f.normalize();
		if (f.empty()) { 
			cout << P << endl;
			continue; 
		}

        FPS<mint> x(2, 0);
        x[1] = 1; // 多項式 x
		FPS<mint> g = modpow(x, P, f) - x;
		FPS<mint> res = gcd(f, g);

		cout << (int)res.size() - 1 << endl;
    }
}
accuracy: 1
time_ms: 230
memory_kb: 3644
final_rank: 14

code_snippet: #include <iostream>
#include <vector>
#include <cmath>
using namespace std;


// Fp体上の多項式（MOD = P）
inline long long mod(long long a, long long m) {
	return (a % m + m) % m;
}

long long pow(long long a, long long n, long long m) {
	if (n == 0) return 1 % m;
	long long t = pow(a, n / 2, m);
	t = mod(t * t, m);
	if (n & 1) t = mod(t * a, m);
	return t;
}

long long inv(long long a, long long m) {
	long long b = m, u = 1, v = 0;
	while (b) {
		long long t = a / b;
		a -= t*b; swap(a, b);
		u -= t*v; swap(u, v);
	}
	return mod(u, m);
}

struct ModPolynomial : vector<long long> {
	long long MOD = 1000000007;                                              // to be set
	ModPolynomial() : vector<long long>(1, 0) { }
	ModPolynomial(long long num) : vector<long long>(1, num) { }
	ModPolynomial(int size, long long num) : vector<long long>(size, num) { }
	ModPolynomial(vector<long long> vec) { (*this) = vec; }

	void init(long long num) { *this = vector<long long>(1, num); }
	void init(int size, long long num) { *this = vector<long long>(size, num); }
	void init(vector<long long> vec) { *this = vec; }
	ModPolynomial& normalize() {
		for (int i = 0; i < (*this).size(); ++i) (*this)[i] = mod((*this)[i], MOD);
		while ((*this).size() > 1 && (*this).back() == 0) (*this).pop_back();
		return (*this);
	}

	inline ModPolynomial operator - () {
		for (int i = 0; i < (*this).size(); ++i) (*this)[i] = (*this)[i] * (-1);
		return (*this).normalize();
	}
	inline const ModPolynomial& operator += (const ModPolynomial &x);
	inline const ModPolynomial& operator -= (const ModPolynomial &x);
	inline const ModPolynomial& operator *= (long long x);
	inline const ModPolynomial& operator *= (const ModPolynomial &x);
	inline const ModPolynomial& operator /= (long long x);
	inline const ModPolynomial& operator /= (const ModPolynomial &x);
	inline const ModPolynomial& operator %= (long long x);
	inline const ModPolynomial& operator %= (const ModPolynomial &x);
};

inline bool operator > (ModPolynomial x, ModPolynomial y) { return x.size() > y.size(); }
inline bool operator < (ModPolynomial x, ModPolynomial y) { return y > x; }
inline bool operator <= (ModPolynomial x, ModPolynomial y) { return !(y < x); }
inline bool operator >= (ModPolynomial x, ModPolynomial y) { return !(x < y); }
inline bool operator != (ModPolynomial x, ModPolynomial y) { return x < y || y < x; }
inline bool operator == (ModPolynomial x, ModPolynomial y) { return !(x < y) && !(y < x); }

ostream &operator << (ostream &os, ModPolynomial x) {
	for (int i = (int)x.size() - 1; i >= 0; --i) {
		if (i != (int)x.size() - 1) os << abs(x[i]); else os << x[i];
		if (i != 0) {
			os << "x"; if (i != 1) os << "^" << i; os << " ";
			if (x[i - 1] < 0) os << "- "; else os << "+ ";
		}
	}
	return os;
}

inline ModPolynomial operator + (ModPolynomial x, ModPolynomial y) {
	x.normalize(); y.normalize();
	while (x.size() > y.size()) y.push_back(0);
	while (y.size() > x.size()) x.push_back(0);
	ModPolynomial z((int)x.size(), 0);
	z.MOD = x.MOD;
	for (int i = 0; i < (int)x.size(); ++i) z[i] = x[i] + y[i];
	return z.normalize();
}
inline ModPolynomial operator - (ModPolynomial x, ModPolynomial y) {
	y = -y;
	return x + y;
}
inline ModPolynomial operator * (ModPolynomial x, long long a) {
	x.normalize();
	ModPolynomial z((int)x.size(), 0);
	z.MOD = x.MOD;
	for (int i = 0; i < (int)x.size(); ++i) z[i] = mod(x[i] * a, x.MOD);
	return z.normalize();
}
inline ModPolynomial operator * (ModPolynomial x, ModPolynomial y) {
	x.normalize(); y.normalize();
	ModPolynomial z((int)x.size() + (int)y.size() - 1, 0);
	z.MOD = x.MOD;
	for (int i = 0; i < (int)x.size(); ++i) for (int j = 0; j < (int)y.size(); ++j) z[i + j] = mod(z[i + j] + x[i] * y[j], z.MOD);
	return z.normalize();
}
pair<ModPolynomial, long long> divmod(ModPolynomial x, long long a) {
	x.normalize();
	for (int i = (int)x.size() - 1; i >= 0; --i) x[i] = mod(x[i] * inv(a, x.MOD), x.MOD);
	return pair<ModPolynomial, long long>(x, 0);
}
ModPolynomial operator / (ModPolynomial x, long long a) {
	x.normalize();
	return divmod(x, a).first;
}
long long operator % (ModPolynomial x, long long a) {
	x.normalize();
	return divmod(x, a).second;
}
pair<ModPolynomial, ModPolynomial> divmod(ModPolynomial x, ModPolynomial y) {
	x.normalize(); y.normalize();
	if (x.size() < y.size()) return make_pair(0, x);
	if (y.size() == 1) return divmod(x, y.back());
	ModPolynomial q((int)x.size() - (int)y.size() + 1, 0);
	for (int i = (int)x.size() - 1; i >= (int)y.size() - 1; --i) {
		long long div = mod(x[i] * inv(y.back(), x.MOD), x.MOD);
		q[i - (int)y.size() + 1] = div;
		for (int j = 0; j < (int)y.size(); ++j) x[i + j - (int)y.size() + 1] = mod(x[i + j - (int)y.size() + 1] - y[j] * div, x.MOD);
	}
	return make_pair(q, x.normalize());
}
ModPolynomial operator / (ModPolynomial x, ModPolynomial y) {
	x.normalize(); y.normalize();
	return divmod(x, y).first;
}
ModPolynomial operator % (ModPolynomial x, ModPolynomial y) {
	x.normalize(); y.normalize();
	return divmod(x, y).second;
}
ModPolynomial pow(ModPolynomial a, long long n) {
	a.normalize();
	ModPolynomial res(1, 1);
	res.MOD = a.MOD;
	while (n > 0) { if (n & 1) { res = res * a; } a = a * a; n >>= 1; }
	return res;
}
ModPolynomial pow(ModPolynomial a, long long n, ModPolynomial PMOD) {
	a.normalize(); PMOD.normalize();
	ModPolynomial res(1, 1);
	res.MOD = a.MOD;
	while (n > 0) { if (n & 1) { res = (res * a) % PMOD; } a = (a * a) % PMOD; n >>= 1; }
	return res;
}
ModPolynomial gcd(ModPolynomial x, ModPolynomial y) {
	x.normalize(); y.normalize();
	if (y.size() == 1 && y.back() == 0) return x;
	else return gcd(y, x%y);
}
inline const ModPolynomial& ModPolynomial::operator += (const ModPolynomial &x) { *this = *this + x; return *this; }
inline const ModPolynomial& ModPolynomial::operator -= (const ModPolynomial &x) { *this = *this - x; return *this; }
inline const ModPolynomial& ModPolynomial::operator *= (long long x) { *this = *this * x; return *this; }
inline const ModPolynomial& ModPolynomial::operator *= (const ModPolynomial &x) { *this = *this * x; return *this; }
inline const ModPolynomial& ModPolynomial::operator /= (long long x) { *this = *this / x; return *this; }
inline const ModPolynomial& ModPolynomial::operator /= (const ModPolynomial &x) { *this = *this / x; return *this; }
inline const ModPolynomial& ModPolynomial::operator %= (long long x) { *this = *this % x; return *this; }
inline const ModPolynomial& ModPolynomial::operator %= (const ModPolynomial &x) { *this = *this % x; return *this; }




int main() {
	long long N, P;
	while (cin >> N >> P) {
		if (N == 0) break;

		ModPolynomial f(N + 1, 0);
		f.MOD = P;
		for (int i = 0; i < N + 1; ++i) cin >> f[i];
		f.normalize();

		if (f.size() == 1 && f.back() == 0) { 
			cout << P << endl;
			continue; 
		}

		ModPolynomial x(2, 0); // 多項式 x
		x.MOD = P;
		x[1] = 1;
		ModPolynomial xp_minus_x = pow(x, P, f) - x;
		ModPolynomial g = gcd(f, xp_minus_x);

		cout << (int)g.size() - 1 << endl;
	}
}
accuracy: 1
time_ms: 50
memory_kb: 3296
final_rank: 6

code_snippet: #include <iostream>
#include <sstream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <ctime>
#include <cstring>
#include <string>
#include <vector>
#include <stack>
#include <queue>
#include <deque>
#include <map>
#include <set>
#include <bitset>
#include <numeric>
#include <utility>
#include <iomanip>
#include <algorithm>
#include <functional>
using namespace std;

typedef long long ll;
typedef vector<int> vint;
typedef vector<long long> vll;
typedef pair<int,int> pint;
typedef pair<long long, long long> pll;

#define MP make_pair
#define PB push_back
#define ALL(s) (s).begin(),(s).end()
#define EACH(i, s) for (__typeof__((s).begin()) i = (s).begin(); i != (s).end(); ++i)
#define COUT(x) cout << #x << " = " << (x) << " (L" << __LINE__ << ")" << endl

template<class T> inline bool chmax(T& a, T b) { if (a < b) { a = b; return 1; } return 0; }
template<class T> inline bool chmin(T& a, T b) { if (a > b) { a = b; return 1; } return 0; }
template<class T1, class T2> ostream& operator << (ostream &s, pair<T1,T2> P) 
{ return s << '<' << P.first << ", " << P.second << '>'; }
template<class T> ostream& operator << (ostream &s, vector<T> P) 
{ for (int i = 0; i < P.size(); ++i) { if (i > 0) { s << " "; } s << P[i]; } return s; }
template<class T1, class T2> ostream& operator << (ostream &s, map<T1,T2> P) 
{ EACH(it, P) { s << "<" << it->first << "->" << it->second << "> "; } return s; }







long long MOD;

inline long long mod(long long a, long long m) {
    return (a % m + m) % m;
}

long long pow(long long a, long long n, long long m) {
    if (n == 0) return 1 % m;
    long long t = pow(a, n/2, m);
    t = mod(t * t, m);
    if (n & 1) t = mod(t * a, m);
    return t;
}

long long inv(long long a, long long m) {
    long long b = m, u = 1, v = 0;
    while (b) {
        long long t = a/b;
        a -= t*b; swap(a, b);
        u -= t*v; swap(u, v);
    }
    return mod(u, m);
}

struct ModPolynomial : vector<long long> {
    ModPolynomial() : vector<long long>(1, 0) { }
    ModPolynomial(long long num) : vector<long long>(1, num) { }
    ModPolynomial(int size, long long num) : vector<long long>(size, num) { }
    ModPolynomial(vector<long long> vec) { (*this) = vec; }
    
    ModPolynomial& normalize() {
        for (int i = 0; i < (*this).size(); ++i) (*this)[i] = mod((*this)[i], MOD);
        while ( (*this).size() > 1 && (*this).back() == 0 ) (*this).pop_back();
        return (*this);
    }
    
    inline ModPolynomial operator - () { 
        for (int i = 0; i < (*this).size(); ++i) (*this)[i] = (*this)[i] * (-1); 
        return (*this).normalize();
    }
};

ostream &operator << (ostream &os, ModPolynomial x) {
    for (int i = x.size()-1; i >= 0; --i) { 
        if (i != x.size()-1) os << abs(x[i]); else os << x[i];
        if (i != 0) {
            os << "x"; if (i != 1) os << "^" << i; os << " ";
            if (x[i-1] < 0) os << "- "; else os << "+ ";
        }
    }
    return os;
}

inline ModPolynomial operator + (ModPolynomial x, ModPolynomial y) {
    while (x.size() > y.size()) y.push_back(0);
    while (y.size() > x.size()) x.push_back(0);
    ModPolynomial z((int)x.size(), 0);
    for (int i = 0; i < x.size(); ++i) z[i] = x[i] + y[i];
    return z.normalize();
} 
inline ModPolynomial operator - (ModPolynomial x, ModPolynomial y) {
    y = -y;
    return x + y;
}
inline ModPolynomial operator * (ModPolynomial x, ModPolynomial y) {
    ModPolynomial z((int)x.size() + (int)y.size() - 1, 0);
    for (int i = 0; i < x.size(); ++i) for (int j = 0; j < y.size(); ++j) z[i+j] = mod(z[i+j] + x[i] * y[j], MOD);
    return z.normalize();
}
pair<ModPolynomial,long long> divmod(ModPolynomial x, long long a) {
    for (int i = x.size()-1; i >= 0; --i) x[i] = mod(x[i] * inv(a, MOD), MOD);
    return pair<ModPolynomial,long long>(x, 0);
}
pair<ModPolynomial,ModPolynomial> divmod(ModPolynomial x, ModPolynomial y) {
    if (x.size() < y.size()) return make_pair(0, x);
    if (y.size() == 1) return divmod(x, y.back());
    ModPolynomial q((int)x.size() - (int)y.size() + 1, 0);
    for (int i = x.size()-1; i >= y.size()-1; --i) {
        long long div = mod(x[i] * inv(y.back(), MOD), MOD);
        q[i-(int)y.size()+1] = div;
        for (int j = 0; j < y.size(); ++j) x[i+j-(int)y.size()+1] = mod(x[i+j-(int)y.size()+1] - y[j] * div, MOD);
    }
    return make_pair(q, x.normalize());
}
ModPolynomial operator % (ModPolynomial x, ModPolynomial y) {
    return divmod(x, y).second;
}
ModPolynomial pow(ModPolynomial a, long long n, ModPolynomial PMOD) {
    ModPolynomial res(1, 1);
    while (n > 0) { if (n & 1) { res = (res * a) % PMOD; } a = (a * a) % PMOD; n >>= 1;}
    return res;
}
ModPolynomial gcd(ModPolynomial x, ModPolynomial y) {
    if (y.size() == 1 && y.back() == 0) return x;
    else return gcd(y, x%y);
}
ModPolynomial generateX() { ModPolynomial X(2, 0); X[1] = 1; return X; }
ModPolynomial EX = generateX();



long long N, P, a;

int main() {
    while (cin >> N >> P) {
        if (N == 0) break;
        
        MOD = P;
        ModPolynomial pol(N+1, 0);
        for (int i = 0; i < N+1; ++i) cin >> pol[i];
        pol.normalize();
        
        if (pol.size() == 1 && pol.back() == 0) { cout << MOD << endl; continue; }
        
        ModPolynomial check = pow(EX, MOD, pol) - EX;
        ModPolynomial G = gcd(pol, check);
        
        cout << G.size() - 1 << endl;
    }
    return 0;
}
accuracy: 1
time_ms: 60
memory_kb: 1376
final_rank: 1

code_snippet: #include <iostream>
#include <sstream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <ctime>
#include <cstring>
#include <string>
#include <vector>
#include <stack>
#include <queue>
#include <deque>
#include <map>
#include <set>
#include <bitset>
#include <numeric>
#include <utility>
#include <iomanip>
#include <algorithm>
#include <functional>
using namespace std;

typedef long long ll;
typedef vector<int> vint;
typedef vector<long long> vll;
typedef pair<int,int> pint;
typedef pair<long long, long long> pll;

#define MP make_pair
#define PB push_back
#define ALL(s) (s).begin(),(s).end()
#define EACH(i, s) for (__typeof__((s).begin()) i = (s).begin(); i != (s).end(); ++i)
#define COUT(x) cout << #x << " = " << (x) << " (L" << __LINE__ << ")" << endl

template<class T> inline bool chmax(T& a, T b) { if (a < b) { a = b; return 1; } return 0; }
template<class T> inline bool chmin(T& a, T b) { if (a > b) { a = b; return 1; } return 0; }
template<class T1, class T2> ostream& operator << (ostream &s, pair<T1,T2> P) 
{ return s << '<' << P.first << ", " << P.second << '>'; }
template<class T> ostream& operator << (ostream &s, vector<T> P) 
{ for (int i = 0; i < P.size(); ++i) { if (i > 0) { s << " "; } s << P[i]; } return s; }
template<class T1, class T2> ostream& operator << (ostream &s, map<T1,T2> P) 
{ EACH(it, P) { s << "<" << it->first << "->" << it->second << "> "; } return s; }







long long MOD;

inline long long mod(long long a, long long m) {
    return (a % m + m) % m;
}

long long pow(long long a, long long n, long long m) {
    if (n == 0) return 1 % m;
    long long t = pow(a, n/2, m);
    t = mod(t * t, m);
    if (n & 1) t = mod(t * a, m);
    return t;
}

long long inv(long long a, long long m) {
    long long b = m, u = 1, v = 0;
    while (b) {
        long long t = a/b;
        a -= t*b; swap(a, b);
        u -= t*v; swap(u, v);
    }
    return mod(u, m);
}

struct ModPolynomial : vector<long long> {
    ModPolynomial() : vector<long long>(1, 0) { }
    ModPolynomial(long long num) : vector<long long>(1, num) { }
    ModPolynomial(int size, long long num) : vector<long long>(size, num) { }
    ModPolynomial(vector<long long> vec) { (*this) = vec; }
    
    ModPolynomial& normalize() {
        for (int i = 0; i < (*this).size(); ++i) (*this)[i] = mod((*this)[i], MOD);
        while ( (*this).size() > 1 && (*this).back() == 0 ) (*this).pop_back();
        return (*this);
    }
    
    inline ModPolynomial operator - () { 
        for (int i = 0; i < (*this).size(); ++i) (*this)[i] = (*this)[i] * (-1); 
        return (*this).normalize();
    }
    inline const ModPolynomial& operator += (const ModPolynomial &x);
    inline const ModPolynomial& operator -= (const ModPolynomial &x);
    inline const ModPolynomial& operator *= (long long x);
    inline const ModPolynomial& operator *= (const ModPolynomial &x);
    inline const ModPolynomial& operator /= (long long x);
    inline const ModPolynomial& operator /= (const ModPolynomial &x);
    inline const ModPolynomial& operator %= (long long x);
    inline const ModPolynomial& operator %= (const ModPolynomial &x);
};

inline bool operator > (ModPolynomial x, ModPolynomial y) { return x.size() > y.size(); }
inline bool operator < (ModPolynomial x, ModPolynomial y) { return y > x; }
inline bool operator <= (ModPolynomial x, ModPolynomial y) { return !(y < x); }
inline bool operator >= (ModPolynomial x, ModPolynomial y) { return !(x < y); }
inline bool operator != (ModPolynomial x, ModPolynomial y) { return x < y || y < x; }
inline bool operator == (ModPolynomial x, ModPolynomial y) { return !(x < y) && !(y < x); }

ostream &operator << (ostream &os, ModPolynomial x) {
    for (int i = x.size()-1; i >= 0; --i) { 
        if (i != x.size()-1) os << abs(x[i]); else os << x[i];
        if (i != 0) {
            os << "x"; if (i != 1) os << "^" << i; os << " ";
            if (x[i-1] < 0) os << "- "; else os << "+ ";
        }
    }
    return os;
}

inline ModPolynomial operator + (ModPolynomial x, ModPolynomial y) {
    //x.normalize(); y.normalize();
    while (x.size() > y.size()) y.push_back(0);
    while (y.size() > x.size()) x.push_back(0);
    ModPolynomial z((int)x.size(), 0);
    for (int i = 0; i < x.size(); ++i) z[i] = x[i] + y[i];
    return z.normalize();
} 
inline ModPolynomial operator - (ModPolynomial x, ModPolynomial y) {
    y = -y;
    return x + y;
}
inline ModPolynomial operator * (ModPolynomial x, ModPolynomial y) {
    //x.normalize(); y.normalize();
    ModPolynomial z((int)x.size() + (int)y.size() - 1, 0);
    for (int i = 0; i < x.size(); ++i) for (int j = 0; j < y.size(); ++j) z[i+j] = mod(z[i+j] + x[i] * y[j], MOD);
    return z.normalize();
}
pair<ModPolynomial,long long> divmod(ModPolynomial x, long long a) {
    //x.normalize();
    for (int i = x.size()-1; i >= 0; --i) x[i] = mod(x[i] * inv(a, MOD), MOD);
    return pair<ModPolynomial,long long>(x, 0);
}
pair<ModPolynomial,ModPolynomial> divmod(ModPolynomial x, ModPolynomial y) {
    //x.normalize(); y.normalize();
    if (x.size() < y.size()) return make_pair(0, x);
    if (y.size() == 1) return divmod(x, y.back());
    ModPolynomial q((int)x.size() - (int)y.size() + 1, 0);
    for (int i = x.size()-1; i >= y.size()-1; --i) {
        long long div = mod(x[i] * inv(y.back(), MOD), MOD);
        q[i-(int)y.size()+1] = div;
        for (int j = 0; j < y.size(); ++j) x[i+j-(int)y.size()+1] = mod(x[i+j-(int)y.size()+1] - y[j] * div, MOD);
    }
    return make_pair(q, x.normalize());
}
ModPolynomial operator % (ModPolynomial x, ModPolynomial y) {
    //x.normalize(); y.normalize();
    return divmod(x, y).second;
}
ModPolynomial pow(ModPolynomial a, long long n, ModPolynomial PMOD) {
    //a.normalize(); PMOD.normalize();
    ModPolynomial res(1, 1);
    while (n > 0) { if (n & 1) { res = (res * a) % PMOD; } a = (a * a) % PMOD; n >>= 1;}
    return res;
}
ModPolynomial gcd(ModPolynomial x, ModPolynomial y) {
    //x.normalize(); y.normalize();
    if (y.size() == 1 && y.back() == 0) return x;
    else return gcd(y, x%y);
}
ModPolynomial generateX() { ModPolynomial X(2, 0); X[1] = 1; return X; }
ModPolynomial EX = generateX();



long long N, P, a;

int main() {
    //freopen( "/Users/macuser/Dropbox/Contest/test_00.in", "r", stdin );
    while (cin >> N >> P) {
        if (N == 0) break;
        
        MOD = P;
        ModPolynomial pol(N+1, 0);
        for (int i = 0; i < N+1; ++i) cin >> pol[i];
        pol.normalize();
        
        if (pol.size() == 1 && pol.back() == 0) { cout << MOD << endl; continue; }
        
        ModPolynomial check = pow(EX, MOD, pol) - EX;
        ModPolynomial G = gcd(pol, check);
        
        cout << G.size() - 1 << endl;
    }
    return 0;
}
accuracy: 1
time_ms: 60
memory_kb: 1376
final_rank: 1

code_snippet: #include <iostream>
#include <sstream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <ctime>
#include <cstring>
#include <string>
#include <vector>
#include <stack>
#include <queue>
#include <deque>
#include <map>
#include <set>
#include <bitset>
#include <numeric>
#include <utility>
#include <iomanip>
#include <algorithm>
#include <functional>
using namespace std;

typedef long long ll;
typedef vector<int> vint;
typedef vector<long long> vll;
typedef pair<int,int> pint;
typedef pair<long long, long long> pll;

#define MP make_pair
#define PB push_back
#define ALL(s) (s).begin(),(s).end()
#define EACH(i, s) for (__typeof__((s).begin()) i = (s).begin(); i != (s).end(); ++i)
#define COUT(x) cout << #x << " = " << (x) << " (L" << __LINE__ << ")" << endl

template<class T> inline bool chmax(T& a, T b) { if (a < b) { a = b; return 1; } return 0; }
template<class T> inline bool chmin(T& a, T b) { if (a > b) { a = b; return 1; } return 0; }
template<class T1, class T2> ostream& operator << (ostream &s, pair<T1,T2> P) 
{ return s << '<' << P.first << ", " << P.second << '>'; }
template<class T> ostream& operator << (ostream &s, vector<T> P) 
{ for (int i = 0; i < P.size(); ++i) { if (i > 0) { s << " "; } s << P[i]; } return s; }
template<class T1, class T2> ostream& operator << (ostream &s, map<T1,T2> P) 
{ EACH(it, P) { s << "<" << it->first << "->" << it->second << "> "; } return s; }







long long MOD;

inline long long mod(long long a, long long m) {
    return (a % m + m) % m;
}

long long pow(long long a, long long n, long long m) {
    if (n == 0) return 1 % m;
    long long t = pow(a, n/2, m);
    t = mod(t * t, m);
    if (n & 1) t = mod(t * a, m);
    return t;
}

long long inv(long long a, long long m) {
    long long b = m, u = 1, v = 0;
    while (b) {
        long long t = a/b;
        a -= t*b; swap(a, b);
        u -= t*v; swap(u, v);
    }
    return mod(u, m);
}

struct ModPolynomial : vector<long long> {
    ModPolynomial() : vector<long long>(1, 0) { }
    ModPolynomial(long long num) : vector<long long>(1, num) { }
    ModPolynomial(int size, long long num) : vector<long long>(size, num) { }
    ModPolynomial(vector<long long> vec) { (*this) = vec; }
    
    ModPolynomial& normalize() {
        for (int i = 0; i < (*this).size(); ++i) (*this)[i] = mod((*this)[i], MOD);
        while ( (*this).size() > 1 && (*this).back() == 0 ) (*this).pop_back();
        return (*this);
    }
    
    inline ModPolynomial operator - () { 
        for (int i = 0; i < (*this).size(); ++i) (*this)[i] = (*this)[i] * (-1); 
        return (*this).normalize();
    }
    inline const ModPolynomial& operator += (const ModPolynomial &x);
    inline const ModPolynomial& operator -= (const ModPolynomial &x);
    inline const ModPolynomial& operator *= (long long x);
    inline const ModPolynomial& operator *= (const ModPolynomial &x);
    inline const ModPolynomial& operator /= (long long x);
    inline const ModPolynomial& operator /= (const ModPolynomial &x);
    inline const ModPolynomial& operator %= (long long x);
    inline const ModPolynomial& operator %= (const ModPolynomial &x);
};

inline bool operator > (ModPolynomial x, ModPolynomial y) { return x.size() > y.size(); }
inline bool operator < (ModPolynomial x, ModPolynomial y) { return y > x; }
inline bool operator <= (ModPolynomial x, ModPolynomial y) { return !(y < x); }
inline bool operator >= (ModPolynomial x, ModPolynomial y) { return !(x < y); }
inline bool operator != (ModPolynomial x, ModPolynomial y) { return x < y || y < x; }
inline bool operator == (ModPolynomial x, ModPolynomial y) { return !(x < y) && !(y < x); }

ostream &operator << (ostream &os, ModPolynomial x) {
    for (int i = x.size()-1; i >= 0; --i) { 
        if (i != x.size()-1) os << abs(x[i]); else os << x[i];
        if (i != 0) {
            os << "x"; if (i != 1) os << "^" << i; os << " ";
            if (x[i-1] < 0) os << "- "; else os << "+ ";
        }
    }
    return os;
}

inline ModPolynomial operator + (ModPolynomial x, ModPolynomial y) {
    x.normalize(); y.normalize();
    while (x.size() > y.size()) y.push_back(0);
    while (y.size() > x.size()) x.push_back(0);
    ModPolynomial z((int)x.size(), 0);
    for (int i = 0; i < x.size(); ++i) z[i] = x[i] + y[i];
    return z.normalize();
} 
inline ModPolynomial operator - (ModPolynomial x, ModPolynomial y) {
    y = -y;
    return x + y;
}
inline ModPolynomial operator * (ModPolynomial x, long long a) {
    x.normalize();
    ModPolynomial z((int)x.size(), 0);
    for (int i = 0; i < x.size(); ++i) z[i] = mod(x[i] * a, MOD);
    return z.normalize();
}
inline ModPolynomial operator * (ModPolynomial x, ModPolynomial y) {
    //x.normalize(); y.normalize();
    ModPolynomial z((int)x.size() + (int)y.size() - 1, 0);
    for (int i = 0; i < x.size(); ++i) for (int j = 0; j < y.size(); ++j) z[i+j] = mod(z[i+j] + x[i] * y[j], MOD);
    return z.normalize();
}
pair<ModPolynomial,long long> divmod(ModPolynomial x, long long a) {
    x.normalize();
    for (int i = x.size()-1; i >= 0; --i) x[i] = mod(x[i] * inv(a, MOD), MOD);
    return pair<ModPolynomial,long long>(x, 0);
}
ModPolynomial operator / (ModPolynomial x, long long a) {
    x.normalize();
    return divmod(x, a).first;
}
long long operator % (ModPolynomial x, long long a) {
    x.normalize();
    return divmod(x, a).second;
}
pair<ModPolynomial,ModPolynomial> divmod(ModPolynomial x, ModPolynomial y) {
    x.normalize(); y.normalize();
    if (x.size() < y.size()) return make_pair(0, x);
    if (y.size() == 1) return divmod(x, y.back());
    ModPolynomial q((int)x.size() - (int)y.size() + 1, 0);
    for (int i = x.size()-1; i >= y.size()-1; --i) {
        long long div = mod(x[i] * inv(y.back(), MOD), MOD);
        q[i-(int)y.size()+1] = div;
        for (int j = 0; j < y.size(); ++j) x[i+j-(int)y.size()+1] = mod(x[i+j-(int)y.size()+1] - y[j] * div, MOD);
    }
    return make_pair(q, x.normalize());
}
ModPolynomial operator / (ModPolynomial x, ModPolynomial y) {
    //x.normalize(); y.normalize();
    return divmod(x, y).first;
}
ModPolynomial operator % (ModPolynomial x, ModPolynomial y) {
    //x.normalize(); y.normalize();
    return divmod(x, y).second;
}
ModPolynomial pow(ModPolynomial a, long long n) {
    a.normalize();
    ModPolynomial res(1, 1);
    while (n > 0) { if (n & 1) { res = res * a; } a = a * a; n >>= 1;}
    return res;
}
ModPolynomial pow(ModPolynomial a, long long n, ModPolynomial PMOD) {
    a.normalize(); PMOD.normalize();
    ModPolynomial res(1, 1);
    while (n > 0) { if (n & 1) { res = (res * a) % PMOD; } a = (a * a) % PMOD; n >>= 1;}
    return res;
}
ModPolynomial gcd(ModPolynomial x, ModPolynomial y) {
    x.normalize(); y.normalize();
    if (y.size() == 1 && y.back() == 0) return x;
    else return gcd(y, x%y);
}
inline const ModPolynomial& ModPolynomial::operator += (const ModPolynomial &x) {*this = *this + x; return *this;}
inline const ModPolynomial& ModPolynomial::operator -= (const ModPolynomial &x) {*this = *this - x; return *this;}
inline const ModPolynomial& ModPolynomial::operator *= (long long x) {*this = *this * x; return *this;}
inline const ModPolynomial& ModPolynomial::operator *= (const ModPolynomial &x) {*this = *this * x; return *this;}
inline const ModPolynomial& ModPolynomial::operator /= (long long x) {*this = *this / x; return *this;}
inline const ModPolynomial& ModPolynomial::operator /= (const ModPolynomial &x) {*this = *this / x; return *this;}
inline const ModPolynomial& ModPolynomial::operator %= (long long x) {*this = *this % x; return *this;}
inline const ModPolynomial& ModPolynomial::operator %= (const ModPolynomial &x) {*this = *this % x; return *this;}
ModPolynomial generateX() { ModPolynomial X(2, 0); X[1] = 1; return X; }
ModPolynomial EX = generateX();



long long N, P, a;

int main() {
    //freopen( "/Users/macuser/Dropbox/Contest/test_00.in", "r", stdin );
    
//    MOD = 11;
//    ModPolynomial p(3, 0.0), q(4, 0.0);
//    p[0] = 8; p[1] = 7; p[2] = -2;
//    q[0] = 9; q[1] = -5; q[2] = -4; q[3] = 6;
//    
//    p.normalize(); q.normalize();
//    COUT(p);
//    COUT(q);
//    COUT(p+q);
//    COUT(p-q);
//    COUT(q*p);
//    COUT(p*q);
//    COUT(q/p);
//    COUT(q%p);
//    COUT(p/q);
//    COUT(p%q);
//    COUT(gcd(p,q));
    
    while (cin >> N >> P) {
        if (N == 0) break;
        
        MOD = P;
        ModPolynomial pol(N+1, 0);
        for (int i = 0; i < N+1; ++i) cin >> pol[i];
        pol.normalize();
        
        //COUT(pol);
        
        if (pol.size() == 1 && pol.back() == 0) { cout << MOD << endl; continue; }
        
        ModPolynomial check = pow(EX, MOD, pol) - EX;
        
        //COUT(check);
        
        ModPolynomial G = gcd(pol, check);
        
        cout << G.size() - 1 << endl;
    }
    return 0;
}
accuracy: 1
time_ms: 70
memory_kb: 1380
final_rank: 3

code_snippet: #include <iostream>
#include <sstream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <ctime>
#include <cstring>
#include <string>
#include <vector>
#include <stack>
#include <queue>
#include <deque>
#include <map>
#include <set>
#include <bitset>
#include <numeric>
#include <utility>
#include <iomanip>
#include <algorithm>
#include <functional>
using namespace std;

typedef long long ll;
typedef vector<int> vint;
typedef vector<long long> vll;
typedef pair<int,int> pint;
typedef pair<long long, long long> pll;

#define MP make_pair
#define PB push_back
#define ALL(s) (s).begin(),(s).end()
#define EACH(i, s) for (__typeof__((s).begin()) i = (s).begin(); i != (s).end(); ++i)
#define COUT(x) cout << #x << " = " << (x) << " (L" << __LINE__ << ")" << endl

template<class T> inline bool chmax(T& a, T b) { if (a < b) { a = b; return 1; } return 0; }
template<class T> inline bool chmin(T& a, T b) { if (a > b) { a = b; return 1; } return 0; }
template<class T1, class T2> ostream& operator << (ostream &s, pair<T1,T2> P) 
{ return s << '<' << P.first << ", " << P.second << '>'; }
template<class T> ostream& operator << (ostream &s, vector<T> P) 
{ for (int i = 0; i < P.size(); ++i) { if (i > 0) { s << " "; } s << P[i]; } return s; }
template<class T1, class T2> ostream& operator << (ostream &s, map<T1,T2> P) 
{ EACH(it, P) { s << "<" << it->first << "->" << it->second << "> "; } return s; }







long long MOD;

inline long long mod(long long a, long long m) {
    return (a % m + m) % m;
}

long long pow(long long a, long long n, long long m) {
    if (n == 0) return 1 % m;
    long long t = pow(a, n/2, m);
    t = mod(t * t, m);
    if (n & 1) t = mod(t * a, m);
    return t;
}

long long inv(long long a, long long m) {
    long long b = m, u = 1, v = 0;
    while (b) {
        long long t = a/b;
        a -= t*b; swap(a, b);
        u -= t*v; swap(u, v);
    }
    return mod(u, m);
}

struct ModPolynomial : vector<long long> {
    ModPolynomial() : vector<long long>(1, 0) { }
    ModPolynomial(long long num) : vector<long long>(1, num) { }
    ModPolynomial(int size, long long num) : vector<long long>(size, num) { }
    ModPolynomial(vector<long long> vec) { (*this) = vec; }
    
    ModPolynomial& normalize() {
        for (int i = 0; i < (*this).size(); ++i) (*this)[i] = mod((*this)[i], MOD);
        while ( (*this).size() > 1 && (*this).back() == 0 ) (*this).pop_back();
        return (*this);
    }
    
    inline ModPolynomial operator - () { 
        for (int i = 0; i < (*this).size(); ++i) (*this)[i] = (*this)[i] * (-1); 
        return (*this).normalize();
    }
    inline const ModPolynomial& operator += (const ModPolynomial &x);
    inline const ModPolynomial& operator -= (const ModPolynomial &x);
    inline const ModPolynomial& operator *= (long long x);
    inline const ModPolynomial& operator *= (const ModPolynomial &x);
    inline const ModPolynomial& operator /= (long long x);
    inline const ModPolynomial& operator /= (const ModPolynomial &x);
    inline const ModPolynomial& operator %= (long long x);
    inline const ModPolynomial& operator %= (const ModPolynomial &x);
};

inline bool operator > (ModPolynomial x, ModPolynomial y) { return x.size() > y.size(); }
inline bool operator < (ModPolynomial x, ModPolynomial y) { return y > x; }
inline bool operator <= (ModPolynomial x, ModPolynomial y) { return !(y < x); }
inline bool operator >= (ModPolynomial x, ModPolynomial y) { return !(x < y); }
inline bool operator != (ModPolynomial x, ModPolynomial y) { return x < y || y < x; }
inline bool operator == (ModPolynomial x, ModPolynomial y) { return !(x < y) && !(y < x); }

ostream &operator << (ostream &os, ModPolynomial x) {
    for (int i = x.size()-1; i >= 0; --i) { 
        if (i != x.size()-1) os << abs(x[i]); else os << x[i];
        if (i != 0) {
            os << "x"; if (i != 1) os << "^" << i; os << " ";
            if (x[i-1] < 0) os << "- "; else os << "+ ";
        }
    }
    return os;
}

inline ModPolynomial operator + (ModPolynomial x, ModPolynomial y) {
    x.normalize(); y.normalize();
    while (x.size() > y.size()) y.push_back(0);
    while (y.size() > x.size()) x.push_back(0);
    ModPolynomial z((int)x.size(), 0);
    for (int i = 0; i < x.size(); ++i) z[i] = x[i] + y[i];
    return z.normalize();
} 
inline ModPolynomial operator - (ModPolynomial x, ModPolynomial y) {
    y = -y;
    return x + y;
}
inline ModPolynomial operator * (ModPolynomial x, long long a) {
    x.normalize();
    ModPolynomial z((int)x.size(), 0);
    for (int i = 0; i < x.size(); ++i) z[i] = mod(x[i] * a, MOD);
    return z.normalize();
}
inline ModPolynomial operator * (ModPolynomial x, ModPolynomial y) {
    x.normalize(); y.normalize();
    ModPolynomial z((int)x.size() + (int)y.size() - 1, 0);
    for (int i = 0; i < x.size(); ++i) for (int j = 0; j < y.size(); ++j) z[i+j] = mod(z[i+j] + x[i] * y[j], MOD);
    return z.normalize();
}
pair<ModPolynomial,long long> divmod(ModPolynomial x, long long a) {
    x.normalize();
    for (int i = x.size()-1; i >= 0; --i) x[i] = mod(x[i] * inv(a, MOD), MOD);
    return pair<ModPolynomial,long long>(x, 0);
}
ModPolynomial operator / (ModPolynomial x, long long a) {
    x.normalize();
    return divmod(x, a).first;
}
long long operator % (ModPolynomial x, long long a) {
    x.normalize();
    return divmod(x, a).second;
}
pair<ModPolynomial,ModPolynomial> divmod(ModPolynomial x, ModPolynomial y) {
    x.normalize(); y.normalize();
    if (x.size() < y.size()) return make_pair(0, x);
    if (y.size() == 1) return divmod(x, y.back());
    ModPolynomial q((int)x.size() - (int)y.size() + 1, 0);
    for (int i = x.size()-1; i >= y.size()-1; --i) {
        long long div = mod(x[i] * inv(y.back(), MOD), MOD);
        q[i-(int)y.size()+1] = div;
        for (int j = 0; j < y.size(); ++j) x[i+j-(int)y.size()+1] = mod(x[i+j-(int)y.size()+1] - y[j] * div, MOD);
    }
    return make_pair(q, x.normalize());
}
ModPolynomial operator / (ModPolynomial x, ModPolynomial y) {
    x.normalize(); y.normalize();
    return divmod(x, y).first;
}
ModPolynomial operator % (ModPolynomial x, ModPolynomial y) {
    x.normalize(); y.normalize();
    return divmod(x, y).second;
}
ModPolynomial pow(ModPolynomial a, long long n) {
    a.normalize();
    ModPolynomial res(1, 1);
    while (n > 0) { if (n & 1) { res = res * a; } a = a * a; n >>= 1;}
    return res;
}
ModPolynomial pow(ModPolynomial a, long long n, ModPolynomial PMOD) {
    a.normalize(); PMOD.normalize();
    ModPolynomial res(1, 1);
    while (n > 0) { if (n & 1) { res = (res * a) % PMOD; } a = (a * a) % PMOD; n >>= 1;}
    return res;
}
ModPolynomial gcd(ModPolynomial x, ModPolynomial y) {
    x.normalize(); y.normalize();
    if (y.size() == 1 && y.back() == 0) return x;
    else return gcd(y, x%y);
}
inline const ModPolynomial& ModPolynomial::operator += (const ModPolynomial &x) {*this = *this + x; return *this;}
inline const ModPolynomial& ModPolynomial::operator -= (const ModPolynomial &x) {*this = *this - x; return *this;}
inline const ModPolynomial& ModPolynomial::operator *= (long long x) {*this = *this * x; return *this;}
inline const ModPolynomial& ModPolynomial::operator *= (const ModPolynomial &x) {*this = *this * x; return *this;}
inline const ModPolynomial& ModPolynomial::operator /= (long long x) {*this = *this / x; return *this;}
inline const ModPolynomial& ModPolynomial::operator /= (const ModPolynomial &x) {*this = *this / x; return *this;}
inline const ModPolynomial& ModPolynomial::operator %= (long long x) {*this = *this % x; return *this;}
inline const ModPolynomial& ModPolynomial::operator %= (const ModPolynomial &x) {*this = *this % x; return *this;}
ModPolynomial generateX() { ModPolynomial X(2, 0); X[1] = 1; return X; }
ModPolynomial EX = generateX();



long long N, P, a;

int main() {
    //freopen( "/Users/macuser/Dropbox/Contest/test_00.in", "r", stdin );
    
//    MOD = 11;
//    ModPolynomial p(3, 0.0), q(4, 0.0);
//    p[0] = 8; p[1] = 7; p[2] = -2;
//    q[0] = 9; q[1] = -5; q[2] = -4; q[3] = 6;
//    
//    p.normalize(); q.normalize();
//    COUT(p);
//    COUT(q);
//    COUT(p+q);
//    COUT(p-q);
//    COUT(q*p);
//    COUT(p*q);
//    COUT(q/p);
//    COUT(q%p);
//    COUT(p/q);
//    COUT(p%q);
//    COUT(gcd(p,q));
    
    while (cin >> N >> P) {
        if (N == 0) break;
        
        MOD = P;
        ModPolynomial pol(N+1, 0);
        for (int i = 0; i < N+1; ++i) cin >> pol[i];
        pol.normalize();
        
        //COUT(pol);
        
        if (pol.size() == 1 && pol.back() == 0) { cout << MOD << endl; continue; }
        
        ModPolynomial check = pow(EX, MOD, pol) - EX;
        
        //COUT(check);
        
        ModPolynomial G = gcd(pol, check);
        
        cout << G.size() - 1 << endl;
    }
    return 0;
}
accuracy: 1
time_ms: 70
memory_kb: 1388
final_rank: 4