#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
int n, p, x, y, inv[101010], iNv[101010], fac[101010];
//欧拉定理求逆元
inline long long fast_pow(int a, int b)
{
long long ans = 1;
while (b)
{
if (b & 1) ans = (a * ans) % p;
a = (a * a) % p;
b >>= 1;
}
return ans;
}
//扩展欧几里得求逆元
void ex_gcd(int a, int b, int & x, int & y)
{
if (b == 0)
{
x = 1,
y = 0;
return;
}
ex_gcd(b, a % b, y, x);
y -= a / b * x;
}
//线性推逆元
void INV()
{
inv[1] = 1;
for (int i = 2; i <= n; ++i)
inv[i] = inv[p % i] * (p - p / i) % p;
}
//线性求阶乘逆元
void INVV()
{
fac[0] = 1;
for (int i = 1; i <= n; ++i) fac[i] = (fac[i - 1] * i) % p;
iNv[n] = fast_pow(fac[n], p - 2);
for (int i = n - 1; i >= 1; --i)
iNv[i] = (iNv[i + 1] * (i + 1)) % p;
}
signed main()
{
std::cin >> n >> p;
ex_gcd(n, p, x, y);
printf("扩展欧几里得:%d\n", x % p);
printf("欧拉定理:%d\n线性推逆元:", fast_pow(n, p - 2));
INV(); INVV();
for (int i = 1; i <= n; ++i) printf("%d ", inv[i]);
printf("\n线性推阶乘逆元:");
for (int i = 1; i <= n; ++i) printf("%d ", iNv[i]);
return 0;
}