1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
#include <iostream>
#include <vector>
using namespace std;
struct ZB1 {
  struct Zbior {
    int const j;
    Zbior *neg;
    Zbior(int j = 0) : j(j), neg(0) {
    }
    virtual ~Zbior() {
    }
    virtual bool check(int value) const {
      return !(value % j);
    }
  };
  struct ZbiorSuma : Zbior {
    Zbior const &a, &b;
    ZbiorSuma(Zbior const &a, Zbior const &b) : a(a), b(b) {
    }
    virtual bool check(int v) const {
      return a.check(v) || b.check(v);
    }
  };
  struct ZbiorIloczyn : Zbior {
    Zbior const &a, &b;
    ZbiorIloczyn(Zbior const &a, Zbior const &b) : a(a), b(b) {
    }
    virtual bool check(int v) const {
      return a.check(v) && b.check(v);
    }
  };
  struct ZbiorNegacja : Zbior {
    Zbior const &a;
    ZbiorNegacja(Zbior const &a) : a(a) {
    }
    virtual bool check(int v) const {
      return !a.check(v);
    }
  };
  int count, m;
  vector< Zbior * > v, tofree;
  ZB1(int n, int m) : count(1 + n), m(m), v(1 + count + m) {
    int i = 0;
    while (++i <= n)
      tofree.push_back(v[i] = new Zbior(i));
  }
  ~ZB1() {
    int i = tofree.size();
    while (i--)
      delete tofree[i];
  }
  void suma(int x, int y) {
    tofree.push_back(v[count++] = new ZbiorSuma(*v[x], *v[y]));
  }
  void iloczyn(int x, int y) {
    tofree.push_back(v[count++] = new ZbiorIloczyn(*v[x], *v[y]));
  }
  void negacja(int x) {
    Zbior *z = v[x];
    if (!z->neg) {
      (z->neg = new ZbiorNegacja(*z))->neg = z;
      tofree.push_back(z->neg);
    }
    v[count++] = z->neg;
  }
  bool check(int value) const {
    return v[count - 1]->check(value);
  }
};
struct ZB2 : ZB1 {
  vector< int > vc, vx, vy;
  ZB2(int n, int m) : ZB1(n, m) {
  }
  void add(int c, int x, int y = 0) {
    vc.push_back(c);
    vx.push_back(x);
    vy.push_back(y);
  }
  void suma(int x, int y) {
    add(1, x, y);
    ZB1::suma(x, y);
  }
  void iloczyn(int x, int y) {
    add(2, x, y);
    ZB1::iloczyn(x, y);
  }
  void negacja(int x) {
    add(3, x);
    ZB1::negacja(x);
  }
  friend ostream &operator<<(ostream &os, const ZB2 &zb2) {
    int i = 0;
    os << zb2.vc.size() << '\n';
    while (i < (int)zb2.vc.size()) {
      os << zb2.vc[i] << ' ' << zb2.vx[i];
      if (zb2.vy[i])
        os << ' ' << zb2.vy[i];
      os << '\n';
      ++i;
    }
    return os;
  }
};
int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(NULL);
  int n, s, i, b = 0;
  cin >> n >> s;
  ZB2 zb2(n, n * 2);
  for (i = 1; i <= n; ++i)
    zb2.negacja(i);
  for (i = 1; i <= n; ++i) {
    if (i > b) {
      if (s) {
        --s;
        cin >> b;
      } else
        b = n + 1;
    }
    if (zb2.check(i) != (i == b)) {
      if (i == b)
        zb2.suma(zb2.count - 1, i);
      else
        zb2.iloczyn(zb2.count - 1, n + i);
    }
  }
  cout << zb2;
}