#include <bits/stdc++.h>
using namespace std;
template <class S, class T>
ostream& operator<<(ostream& o, const pair<S, T>& p) {
  return o << "(" << p.first << "," << p.second << ")";
}
template <class T>
ostream& operator<<(ostream& o, const vector<T>& vc) {
  o << "{";
  for (const T& v : vc) o << v << ",";
  o << "}";
  return o;
}
using ll = long long;
template <class T>
using V = vector<T>;
template <class T>
using VV = vector<vector<T>>;
unsigned int mod = 1;
struct ModInt {
  using uint = unsigned int;
  using ll = long long;
  using ull = unsigned long long;
  uint v;
  ModInt() : v(0) {}
  ModInt(ll v) : v(normS(v % mod + mod)) {}
  explicit operator bool() const { return v != 0; }
  static uint normS(const uint& x) { return (x < mod) ? x : x - mod; }
  static ModInt make(const uint& x) {
    ModInt m;
    m.v = x;
    return m;
  }
  ModInt operator+(const ModInt& b) const { return make(normS(v + b.v)); }
  ModInt operator-(const ModInt& b) const { return make(normS(v + mod - b.v)); }
  ModInt operator-() const { return make(normS(mod - v)); }
  ModInt operator*(const ModInt& b) const { return make((ull)v * b.v % mod); }
  ModInt operator/(const ModInt& b) const { return *this * b.inv(); }
  ModInt& operator+=(const ModInt& b) { return *this = *this + b; }
  ModInt& operator-=(const ModInt& b) { return *this = *this - b; }
  ModInt& operator*=(const ModInt& b) { return *this = *this * b; }
  ModInt& operator/=(const ModInt& b) { return *this = *this / b; }
  ll extgcd(ll a, ll b, ll& x, ll& y) const {
    ll u[] = {a, 1, 0}, v[] = {b, 0, 1};
    while (*v) {
      ll t = *u / *v;
      for (int i = 0; i < (int)(3); i++) swap(u[i] -= t * v[i], v[i]);
    }
    if (u[0] < 0)
      for (int i = 0; i < (int)(3); i++) u[i] = -u[i];
    x = u[1], y = u[2];
    return u[0];
  }
  ModInt inv() const {
    ll x, y;
    extgcd(v, mod, x, y);
    return make(normS(x + mod));
  }
  bool operator==(const ModInt& b) const { return v == b.v; }
  bool operator!=(const ModInt& b) const { return v != b.v; }
  friend istream& operator>>(istream& o, ModInt& x) {
    ll tmp;
    o >> tmp;
    x = ModInt(tmp);
    return o;
  }
  friend ostream& operator<<(ostream& o, const ModInt& x) { return o << x.v; }
};
using mint = ModInt;
const mint zero(0);
const mint one(1);
bool iszero(mint x) { return x.v == 0; }
bool isone(mint x) { return x.v == 1; }
template <class T>
struct Matrix {
  int H, W;
  VV<T> a;
  Matrix() : H(0), W(0) {}
  Matrix(int H, int W) : H(H), W(W), a(VV<T>(H, V<T>(W))) {}
  Matrix(const VV<T>& v) : H(v.size()), W(v[0].size()), a(v) {}
  static Matrix E(int n) {
    Matrix a(n, n);
    for (int i = 0; i < (int)(n); i++) a.set(i, i, 1);
    return a;
  }
  T at(int i, int j) const { return a[i][j]; }
  void set(int i, int j, T v) { a[i][j] = v; }
  Matrix operator+(const Matrix& r) const {
    assert(H == r.H && W == r.W);
    VV<T> v(H, V<T>(W));
    for (int i = 0; i < (int)(H); i++)
      for (int j = 0; j < (int)(W); j++) v[i][j] = a[i][j] + r.a[i][j];
    return Matrix(v);
  }
  Matrix operator-(const Matrix& r) const {
    assert(H == r.H && W == r.W);
    VV<T> v(H, V<T>(W));
    for (int i = 0; i < (int)(H); i++)
      for (int j = 0; j < (int)(W); j++) v[i][j] = a[i][j] - r.a[i][j];
    return Matrix(v);
  }
  Matrix operator*(const Matrix& r) const {
    assert(W == r.H);
    VV<T> v(H, V<T>(r.W));
    for (int i = 0; i < (int)(H); i++)
      for (int k = 0; k < (int)(W); k++)
        for (int j = 0; j < (int)(r.W); j++) v[i][j] += a[i][k] * r.a[k][j];
    return Matrix(v);
  }
  Matrix& operator+=(const Matrix& r) { return (*this) = (*this) + r; }
  Matrix& operator-=(const Matrix& r) { return (*this) = (*this) - r; }
  Matrix& operator*=(const Matrix& r) { return (*this) = (*this) * r; }
  int sweep(int var) {
    int rank = 0;
    vector<bool> used(H);
    for (int j = 0; j < (int)(var); j++) {
      int i = 0;
      while (i < H && (used[i] || iszero(a[i][j]))) i++;
      if (i == H) continue;
      used[i] = true;
      rank++;
      T t = a[i][j];
      for (int k = 0; k < (int)(W); k++) a[i][k] = a[i][k] / t;
      for (int k = 0; k < (int)(H); k++)
        if (k != i) {
          T t = a[k][j];
          for (int l = 0; l < (int)(W); l++) a[k][l] = a[k][l] - a[i][l] * t;
        }
    }
    return rank;
  }
  friend ostream& operator<<(ostream& o, const Matrix& A) {
    for (int i = 0; i < (int)(A.H); i++) {
      for (int j = 0; j < (int)(A.W); j++) o << A.a[i][j] << " ";
      o << endl;
    }
    return o;
  }
};
template <class T>
pair<int, vector<T>> solveLinearEquation(const Matrix<T>& A, vector<T> b) {
  assert(A.H == (int)b.size());
  int H = A.H, W = A.W;
  Matrix<T> X(H, W + 1);
  for (int i = 0; i < (int)(H); i++)
    for (int j = 0; j < (int)(W); j++) X.set(i, j, A.at(i, j));
  for (int i = 0; i < (int)(H); i++) X.set(i, W, b[i]);
  int rank = X.sweep(W);
  for (int i = 0; i < (int)(H); i++) {
    bool allzero = true;
    for (int j = 0; j < (int)(W); j++)
      if (!iszero(X.at(i, j))) allzero = false;
    if (allzero) {
      if (!iszero(X.at(i, W))) {
        return pair<int, vector<T>>(-1, vector<T>());
      }
    }
  }
  vector<bool> done(H);
  vector<T> x(W);
  for (int j = 0; j < (int)(W); j++) {
    int c0 = 0, c1 = 0;
    int I = -1;
    for (int i = 0; i < (int)(H); i++) {
      if (iszero(X.at(i, j)))
        c0++;
      else if (isone(X.at(i, j)))
        c1++, I = i;
    }
    if (c0 == H - 1 && c1 == 1 && !done[I]) {
      x[j] = X.at(I, W);
      done[I] = true;
    }
  }
  return pair<int, vector<T>>(W - rank, x);
}
mint pw(mint x, int d) {
  mint a = 1;
  for (int i = 0; i < (int)(d); i++) a *= x;
  return a;
}
const bool SUBMIT = 1;
int d;
ll p;
mint x, y;
mint a[5000];
int Z = 4999;
void init() {
  ll X, Y;
  cin >> X >> Y;
  x = mint(X);
  y = mint(Y);
  a[0] = x;
  a[1] = y;
  for (int i = 2; i < 5000; i++) a[i] = 1;
}
void add(int x, int y, int z) {
  a[z] = a[x] + a[y];
  if (SUBMIT) printf("+ %d %d %d\n", x + 1, y + 1, z + 1);
}
void ex(int x, int y) {
  a[y] = pw(a[x], d);
  if (SUBMIT) printf("^ %d %d\n", x + 1, y + 1);
}
void ans(int i) {
  assert(a[i] == x * y);
  if (SUBMIT) printf("f %d\n", i + 1);
}
void makezero() {
  ll ad = p - 1;
  for (int i = 0; i < (int)(30); i++) {
    if ((ad >> i) & 1) add(Z, Z - 1, Z);
    add(Z - 1, Z - 1, Z - 1);
  }
  assert(a[Z].v == 0);
}
void set0(int x) { add(Z, Z, x); }
void pro(int x, int y, ll c) {
  c = (c % p + p) % p;
  int T = 3000;
  set0(y);
  set0(T);
  add(T, x, T);
  for (int i = 0; i < (int)(30); i++) {
    if ((c >> i) & 1) add(y, T, y);
    add(T, T, T);
  }
  if (x != y) assert(a[y] == a[x] * c);
}
void sub(int x, int y, int z) {
  int T = 2000;
  pro(y, T, -1);
  add(x, T, z);
}
V<mint> coefs;
void sq(int x, int y) {
  int T = 4000;
  int n = d + 1;
  add(x, Z, T - 1);
  for (int i = 0; i < (int)(n); i++) {
    ex(T - 1, T + i);
    add(T - 1, 20, T - 1);
  }
  for (int i = 0; i < (int)(n); i++) {
    pro(T + i, T + i + 20, coefs[i].v);
  }
  set0(y);
  for (int i = 0; i < (int)(n); i++) {
    add(y, T + i + 20, y);
  }
}
int main() {
  cin >> d >> mod;
  p = mod;
  {
    mint C[20][20];
    for (int i = 0; i < (int)(20); i++) {
      C[i][0] = C[i][i] = 1;
      for (int j = 1; j <= (int)(i - 1); j++)
        C[i][j] = C[i - 1][j - 1] + C[i - 1][j];
    }
    int n = d + 1;
    VV<mint> M(n, V<mint>(n));
    for (int i = 0; i < (int)(n); i++) {
      for (int j = 0; j < (int)(n); j++) {
        mint c = C[d][j];
        for (int _ = 0; _ < (int)(d - j); _++) c *= i;
        M[j][i] = c;
      }
    }
    V<mint> x(n);
    x[2] = 1;
    auto p = solveLinearEquation(Matrix<mint>(M), x);
    assert(p.first != -1);
    coefs = p.second;
  }
  if (!SUBMIT) init();
  makezero();
  add(0, 1, 2);
  sq(0, 3);
  sq(1, 4);
  sq(2, 5);
  sub(5, 3, 5);
  sub(5, 4, 5);
  pro(5, 6, (p + 1) / 2);
  ans(6);
}
