#include <bits/stdc++.h>
using namespace std;
template <typename T>
void debug_out(T t) {
  cerr << t;
}
template <typename A, typename B>
void debug_out(pair<A, B> u) {
  cerr << "(" << u.first << " " << u.second << ")";
}
template <typename T>
void debug_out(vector<T> t) {
  int sz = t.size();
  for (int i = 0; i < sz; i++) {
    debug_out(t[i]);
    if (i != sz - 1) cerr << ", ";
  }
}
template <typename T>
void debug_out(vector<vector<T>> t) {
  int sz = t.size();
  for (int i = 0; i < sz; i++) {
    debug_out(t[i]);
    if (i != sz - 1) cerr << endl;
  }
}
template <typename Head, typename... Tail>
void debug_out(Head H, Tail... T) {
  debug_out(H);
  cerr << " ";
  debug_out(T...);
}
template <typename T>
void debug_out(set<T> a) {
  vector<T> _a;
  for (T t : a) _a.push_back(t);
  debug_out(_a);
}
class MinCostFlow {
 public:
  ;
  struct MCEdge {
    int to, cost, flow;
    MCEdge* next;
    MCEdge() {}
    MCEdge(int t, int c, int f) : to(t), cost(c), flow(f) {}
  };
  const int Infty = 1010101010;
  vector<vector<MCEdge*>> adjList;
  int N, Source, Sink;
  vector<int> dist;
  vector<MCEdge*> prev, Edges;
  inline bool zero_edge(MCEdge& E) { return (E.flow == 0); }
  bool bellman_improve() {
    bool result = false;
    for (int v = 0; v < N; v++) {
      for (MCEdge* E : adjList[v]) {
        int s = E->to;
        if (E->flow == 0) continue;
        int newDist = dist[v] + E->cost;
        if (newDist < dist[s]) {
          dist[s] = newDist;
          prev[s] = E->next;
          result = true;
        }
      }
    }
    return result;
  }
  void bellman_shortest_path() {
    fill(dist.begin(), dist.end(), Infty);
    dist[Source] = 0;
    int maxImprove = N;
    while (bellman_improve() && maxImprove--)
      ;
  }
  int reduce_cost() {
    int result = dist[Sink];
    for (int v = 0; v < N; v++) {
      for (MCEdge* E : adjList[v]) {
        E->cost += dist[v] - dist[E->to];
      }
    }
    return result;
  }
  void dijkstra_shortest_path() {
    fill(dist.begin(), dist.end(), Infty);
    dist[Source] = 0;
    priority_queue<pair<int, int>> Q;
    Q.push(make_pair(0, Source));
    while (!Q.empty()) {
      int dst, v;
      tie(dst, v) = Q.top();
      Q.pop();
      dst = -dst;
      if (dst != dist[v]) continue;
      for (MCEdge* E : adjList[v]) {
        int s = E->to;
        if (E->flow == 0) continue;
        int newDist = dist[v] + E->cost;
        if (newDist < dist[s]) {
          dist[s] = newDist;
          prev[s] = E->next;
          Q.push(make_pair(-newDist, s));
        }
      }
    }
  }
  MinCostFlow() {}
  MinCostFlow(int _N) {
    N = _N;
    dist = vector<int>(N, 0);
    prev.resize(N);
    adjList.resize(N);
    sinkCost = 0;
  }
  ~MinCostFlow() {
    for (MCEdge* E : Edges) delete E;
  }
  int numEdges = 0;
  void add_edge(int u, int v, int flow, int cost) {
    numEdges++;
    MCEdge *E1, *E2;
    E1 = new MCEdge(v, cost, flow);
    E2 = new MCEdge(u, -cost, 0);
    Edges.push_back(E1);
    Edges.push_back(E2);
    E1->next = E2;
    E2->next = E1;
    adjList[u].push_back(E1);
    adjList[v].push_back(E2);
  }
  int sinkCost;
  pair<int, int> get_min_cost_flow(int s, int t) {
    Source = s;
    Sink = t;
    int cost = 0, flow = 0;
    bellman_shortest_path();
    if (dist[Sink] > Infty / 2) return {0, 0};
    sinkCost += reduce_cost();
    while (true) {
      dijkstra_shortest_path();
      if (dist[Sink] > Infty / 2) break;
      sinkCost += reduce_cost();
      int maxSend = Infty;
      for (int v = Sink; v != Source; v = prev[v]->to) {
        maxSend = min(maxSend, prev[v]->next->flow);
      }
      for (int v = Sink; v != Source; v = prev[v]->to) {
        MCEdge* E1 = prev[v];
        MCEdge* E2 = E1->next;
        E1->flow += maxSend;
        E2->flow -= maxSend;
      }
      flow += maxSend;
      cost += maxSend * sinkCost;
    }
    return {flow, cost};
  }
};
template <typename T>
string to_string(T t) {
  ostringstream ss;
  ss << t;
  return ss.str();
}
long long to_num(string t) {
  long long res = 0;
  for (int i = 0; i < (int)t.length(); i++) {
    res *= 10;
    res += t[i] - '0';
  }
  return res;
}
string to_base(long long n, int base) {
  string res;
  while (n) {
    res += to_string(n % base);
    n /= base;
  }
  reverse(res.begin(), res.end());
  return res;
}
int n, m;
int main() {
  cin >> n >> m;
  vector<int> a(n);
  for (int i = 0; i < n; i++) cin >> a[i];
  const int inf = 1e6;
  MinCostFlow d(2 * n + 3);
  d.add_edge(2 * n, 2 * n + 1, m, 0);
  for (int i = 0; i < n; i++) {
    d.add_edge(2 * n + 1, 2 * i, 1, __builtin_popcount(a[i]));
    d.add_edge(2 * i, 2 * i + 1, 1, -inf);
    d.add_edge(2 * i + 1, 2 * n + 2, 1, 0);
    for (int j = i + 1; j < n; j++) {
      int c = (a[j] != a[i]) * __builtin_popcount(a[j]);
      d.add_edge(2 * i + 1, 2 * j, 1, c);
    }
  }
  d.add_edge(2 * n + 1, 2 * n + 2, m, 0);
  pair<int, int> ft = d.get_min_cost_flow(2 * n, 2 * n + 2);
  int ret = ft.second;
  ret += inf * n;
  vector<int> to(n, -1);
  for (int i = 0; i < n; i++) {
    int id = -1;
    for (MinCostFlow::MCEdge* e : d.adjList[2 * i + 1]) {
      int v = e->to;
      if (v <= 2 * i || v >= 2 * n) continue;
      if (e->flow == 1) continue;
      assert(id == -1);
      id = v >> 1;
    }
    if (~id) to[id] = i;
  }
  vector<string> res;
  vector<int> ways(m, -1);
  for (int i = 0; i < n; i++) {
    int id = -1;
    for (int j = 0; j < m; j++) {
      if (ways[j] == to[i]) id = j;
    }
    if (id == -1) {
      for (int j = 0; j < m; j++) {
        if (ways[j] == -1) id = j;
      }
    }
    assert(~id);
    char aa = 'a';
    for (int j = 0; j < id; j++) aa++;
    string p = to_string(aa);
    if (a[ways[id]] != a[i]) {
      res.push_back(p + "=" + to_string(a[i]) + "\n");
    }
    res.push_back("print(" + p + ")\n");
    ways[id] = i;
  }
  cout << res.size() << " " << ret << endl;
  for (string s : res) cout << s;
  return 0;
}
