import std.stdio;
import std.uni;
import std.conv;
import std.container;
import std.functional;
import std.algorithm;
import std.array;
import std.typecons;
import std.range;
import std.numeric;
import std.traits;
import std.variant;
import std.concurrency;

void main(string[] args)
{
  auto n = next!int;
  auto a = next!int(n);
  auto pos1 = new int[](n + 1); pos1[] = -1;
  auto pos2 = new int[](n + 1); pos2[] = -1;
  auto cnt1 = new int[](n);
  auto cnt2 = new int[](n);
  foreach(i, ai; a)
    {
      if (i != 0)
	{
	  cnt1[i] = cnt1[i - 1];
	  cnt2[i] = cnt2[i - 1];
	}
      if (ai == 1)
	{
	  cnt1[i]++;
	  pos1[cnt1[i]] = cast(int) i;
	}
      else
	{
	  cnt2[i]++;
	  pos2[cnt2[i]] = cast(int) i;
	}
    }
  foreach(ref c; pos1) if (c == -1) c = n;
  foreach(ref c; pos2) if (c == -1) c = n;
  auto options = new Tuple!(int, int)[](0);
  debug writeln("pos1 = ", pos1);
  debug writeln("pos2 = ", pos2);
 sTest: foreach(s; 1 .. n + 1)
    {
      debug writeln("trying for s = ", s);
      int i = void;
      int ni = void;
      int sets1 = 0;
      int sets2 = 0;
      int next1 = pos1[s];
      int next2 = pos2[s];
      if (next1 < next2)
	{
	  i = next1;
	  sets1++;
	}
      else
	{
	  i = next2;
	  sets2++;
	}
      while (i < n)
	{
	  debug writeln("in i = ", i, " sets1 = ", sets1, " sets2 = ", sets2);
	  if (i == n - 1)
	    {
	      if (sets1 == sets2)
		continue sTest;
	      if (sets1 > sets2)
		{
		  if (a[i] == 1)
		    options ~= tuple(sets1, s);
		}
	      else
		{
		  if (a[i] == 2)
		    options ~= tuple(sets2, s);
		}
	      continue sTest;
	    }

	  next1 = (cnt1[i] + s <= n)? pos1[cnt1[i] + s] : n;
	  next2 = (cnt2[i] + s <= n)? pos2[cnt2[i] + s] : n;
	  if (next1 < next2)
	    {
	      ni = next1;
	      sets1++;
	    }
	  else
	    {
	      ni = next2;
	      sets2++;
	    }

	  i = ni;
	}
    }
  auto soptions = sort(options);
  writeln(options.length);
  foreach(option; options)
    {
      writeln(option[0], " ", option[1]);
    }
}

static this()
{
  popChar;
}

struct Any(T)
{
  static auto read()
  {
    static if (is(T == char))
      {
	auto res = frontChar;
	popChar;
	return res;
      }
  }
}

struct Unsigned(T)
{
  auto read()
  {
    auto res = T(0);
    while(!frontChar.isDigit) popChar;
    do
      {
	res = res * T(10) + T(frontChar - '0');
	popChar;
      }
    while(frontChar.isDigit);
    return res;
  }
}

struct Matrix(T, alias rows, alias cols)
{
  T[][] _cell;
  alias _cell this;
  // Ring constructor
  this(int n)
  {
    final switch(n)
      {
      case 0:
	_cell = new T[][](rows, cols);
	break;
      case 1:
	debug assert(rows == cols);
	_cell = new T[][](rows, cols);
	foreach(i; 0 .. rows)
	  _cell[i][i] = T(1);
	break;
      }
  }
  // Copy constructor
  this(Matrix!(T, rows, cols) other)
  {
    _cell = new T[][](rows, cols);
    foreach(i; 0 .. rows)
      _cell[i][] = other[i][];
  }
  auto opBinary(string op)(Matrix!(T, rows, cols) other)
       if (op == "+" || op == "-")
	 {
	   auto res = Matrix!(T, rows, cols)(0);
	   foreach(i; 0 .. rows)
	     foreach(j; 0 .. cols)
	       res[i][j] = mixin(q{this[i][j]}, op, q{other[i][j]});
	   return res;
	 }
  auto opBinary(string op, alias otherRows, alias otherCols)(Matrix!(T, otherRows, otherCols) other)
       if (op == "*")
	 {
	   debug assert(cols == otherRows);
	   auto res = Matrix!(T, rows, otherCols)(0);
	   foreach(i; 0 .. rows)
	     foreach(k; 0 .. cols)
	       foreach(j; 0 .. otherCols)
		 res[i][j] += this[i][k] * other[k][j];
	   return res;
	 }
  ref auto opOpAssign(string op)(Matrix!(T, rows, cols) other)
  {
    static if (op == "*")
      {
	debug assert(rows == cols);
	alias n = rows;
	auto res = Matrix!(T, n, n)(0);
	T factor;
	foreach(i; 0 .. n)
	  foreach(k; 0 .. n)
	    foreach(j; 0 .. n)
	      res[i][j] += this[i][k] * other[k][j];
	foreach(i; 0 .. n)
	  this[i][] = res[i][];
      }
    else
      {
	foreach(i; 0 .. rows)
	  foreach(j; 0 .. cols)
	    mixin(q{this[i][j] }, text(op, q{=}), q{ other[i][j];});
      }
    return this;
  }
  mixin powMethod;
}

struct Mod(T, alias mod)
{
  alias This = Mod!(T, mod);
  T _rep;
  this(T t)
  {
    _rep = t % mod;
    if (_rep < 0) _rep += mod;
  }
  static auto plain(T t)
  {
    auto res = Mod!(T, mod)();
    res._rep = t;
    return res;
  }
  static auto fromPositive(T t)
  {
    pragma(inline, true);
    return Mod!(T, mod).plain(t % mod);
  }
  static auto fromNegative(T t)
  {
    pragma(inline, true);
    return Mod!(T, mod).plain(t % mod + mod);
  }
  string toString()
  {
    return to!string(_rep);
  }
  debug invariant
  {
    assert(_rep >= 0 && _rep < mod);
  }
  auto opBinary(string op)(This b)
  {
    static if (op == "+")
      {
	T resrep = _rep + b._rep;
	if (resrep >= mod) resrep -= mod;
	return This.plain(resrep);
      }
    else static if (op == "-")
      {
	T resrep = _rep - b._rep;
	if (resrep < 0) resrep += mod;
	return This.plain(resrep);
      }
    else static if (op == "*")
      {
	return This.fromPositive(_rep * b._rep);
      }
  }
  auto opOpAssign(string op)(This b)
  {
    mixin(q{_rep }, text(op, "="), q{b._rep;});
    static if (op == "+")
      {
	if (_rep >= mod) _rep -= mod;
      }
    else static if (op == "-")
      {
	if (_rep < 0) _rep += mod;
      }
    else static if (op == "*")
      {
	_rep %= mod;
      }
    return this;
  }

  auto opBinary(string op)(long exp)
       if (op == "^^")
	 {
	   return pow(exp);
	 }
  mixin powMethod;
}

mixin template powMethod()
{
  auto pow(this ThisType)(long exp)
    {
      auto res = ThisType(1);
      auto pow = ThisType(this);
      while(exp)
	{
	  if (exp & 1) res *= pow;
	  pow *= pow;
	  exp >>= 1;
	}
      return res;
    }
}
// INPUT
char frontChar;
void popChar()
{
  import core.stdc.stdio;
  frontChar = cast(char) getchar;
  if (feof(stdin)) frontChar = ' ';
}
auto makeArray(T, S...)(S s)
{
  enum brackets = () {
    string res;
    foreach(i; 0 .. s.length)
      res ~= "[]";
    return res;
  } ();
  mixin(q{alias Type = T}, brackets, q{;});
  return new Type(s);
}
template isNumberLike(T)
{
  enum isNumberLike = is(typeof((){T test; test = test + test * test; test *= test;}()));
}
void popWhite()
{
  import std.ascii;
  while (frontChar.isWhite) popChar;
}
void print(T...)(T t)
{
  static foreach(ti; t)
    {
      static if (is(typeof(ti) == string))
	{
	  write(ti, " ");
	}
      else static if (isArray!(typeof(ti)))
	{
	  foreach(e; ti) print(e);
	}
      else static if (isTuple!(typeof(ti)))
	{
	  static foreach(i; ti.length) writesp(ti[i]);
	}
      else
	{
	  write(ti, " ");
	}
    }
}
void println(T...)(T t)
{
  static if (t.length == 0)
    writeln;
  static foreach(ti; t)
    {
      print(ti);
      writeln;
    }
}
auto next(alias T, S...)(S s)
{
  pragma(inline, true);
  static if (s.length > 0)
    {
      auto res = makeArray!(typeof(next!T()))(s);
      S t;
      enum loops = () {
	string res;
	foreach(i; 0 .. s.length)
	  {
	    auto ti = text(q{t[}, i, q{]});
	    res ~= text(q{for(}, ti, q{ = 0;}, ti , q{ < s[}, i, q{];}, ti, q{++)});
	  }
	return res;
      } ();
      enum indexing = () {
	string res = "res";
	foreach(i; 0 .. s.length)
	  res ~= text(q{[t[}, i, q{]]});
	return res;
      } ();
      mixin(loops, indexing, q{ = next!T;});
      return res;
    }
  else
    {
      static if (isNumberLike!T)
	{
	  import std.ascii: isDigit;
	  T res;
	  while(frontChar.isWhite) popChar;
	  T multiplier = T(1);
	  if (frontChar == '-')
	    {
	      multiplier = T(-1);
	      popChar;
	    }
	  else if (frontChar == '+')
	    {
	      popChar;
	    }
	  debug assert(frontChar.isDigit);
	  do
	    {
	      res = res * T(10) + T(frontChar - '0');
	      popChar;
	    }
	  while(frontChar.isDigit);
	  return multiplier * res;
	}
      else static if (is(T == string))
	{
	  import std.ascii: isWhite;
	  string res;
	  while(frontChar.isWhite)
	    popChar;
	  while(!frontChar.isWhite)
	    {
	      res ~= frontChar;
	      popChar;
	    }
	  return res;
	}
      else static if (is(T == char))
	{
	  while(frontChar.isWhite) popChar;
	  auto res = frontChar;
	  popChar;
	  return res;
	}
      else
	{
	  return T.read;
	}
    }
}

import std.stdio;
import std.algorithm;
import std.typecons;

const int MAX = 100005;
int n;
int[MAX] a;
int[MAX] f1, f2, pos1, pos2;
Tuple!(int,int)[MAX] ans;

void main() {
    readf(" %s", n);
    foreach(i; 0..n) readf(" %s", a[i]);

    int c1, c2;
    foreach(i; 0..n) {
        f1[i] = c1-1;
        f2[i] = c2-1;
        if (a[i] == 1) {
            pos1[c1++] = i;
        } else {
            pos2[c2++] = i;
        }
    }

    int numOfAns = 0;

match:
    foreach_reverse(t; 1..n+1) {
        int i = 0;
        int win1, win2;
        while (i < n) {
            int end1 = f1[i] + t < c1 ? pos1[f1[i] + t] : n;
            int end2 = f2[i] + t < c2 ? pos2[f2[i] + t] : n;
            int nextEnd = min(end1, end2);
            if (nextEnd >= n) {
                continue match;
            }
            i = nextEnd + 1;
            if (end1 < end2) {
                win1++;
            } else {
                win2++;
            }
        }
        if ((win1 < win2 && a[n-1] == 2) || (win1 > win2 && a[n-1] == 1))
            ans[numOfAns++] = tuple(max(win1, win2), t);
    }

    ans[0..numOfAns].sort!((x, y) => (x[0] == y[0]) ? x[1] < y[1] : x[0] < y[0]);

    writeln(numOfAns);
    foreach(x; ans[0..numOfAns]) writeln(x[0], " ", x[1]);
}

import std.algorithm;
import std.array;
import std.container;
import std.conv;
import std.exception;
import std.functional;
import std.math;
import std.numeric;
import std.range;
import std.stdio;
import std.string;
import std.typecons;
import core.bitop;

void main ()
{
	int n;
	while (readf (" %s ", &n) > 0)
	{
		auto a = [0] ~ readln.split.map !(to !(int)).array;
		int [] sa = [0];
		foreach (i; 0..n)
		{
			sa ~= sa[i] + (a[i + 1] == 1);
		}
		sa ~= n * 10;
		int [] sb = [0];
		foreach (i; 0..n)
		{
			sb ~= sb[i] + (a[i + 1] == 2);
		}
		sb ~= n * 10;
		int [2] [] res;
		foreach (t; 1..n + 1)
		{
			int pos = 0;
			int ca = 0;
			int cb = 0;
			int last = 0;
			bool ok = true;
			while (pos < n)
			{
				int lo = pos - 1;
				int hi = n;
				while (lo < hi)
				{
					int me = ((lo + hi + 3) >> 1) - 1;
					if (sa[me + 1] - sa[pos] >= t ||
					    sb[me + 1] - sb[pos] >= t)
					{
						hi = me - 1;
					}
					else
					{
						lo = me;
					}
				}

				int next = lo + 1;
				if (sa[next + 1] - sa[pos] == t)
				{
					last = 1;
					ca++;
				}
				else if (sb[next + 1] - sb[pos] == t)
				{
					last = 2;
					cb++;
				}
				else
				{
					assert (next >= n);
					ok = false;
					break;
				}
				pos = next + 1;
			}

			ok &= (last == 1 && ca > cb) ||
			    (last == 2 && ca < cb);
			if (ok)
			{
				res ~= [max (ca, cb), t];
			}
		}

		sort (res);
		writeln (res.length);
		foreach (cur; res)
		{
			writeln (cur[0], ' ', cur[1]);
		}
	}
}

import std.stdio;
import std.algorithm;
import std.typecons;

const int MAX = 100005;
int n;
int[MAX] a;
int[MAX] f1, f2, pos1, pos2;
Tuple!(int,int)[MAX] ans;

void main() {
    readf(" %s", n);
    foreach(i; 0..n) readf(" %s", a[i]);

    int c1, c2;
    foreach(i; 0..n) {
        f1[i] = c1-1;
        f2[i] = c2-1;
        if (a[i] == 1) {
            pos1[c1++] = i;
        } else {
            pos2[c2++] = i;
        }
    }

    int numOfAns = 0;

match:
    foreach_reverse(t; 1..n+1) {
        int i = 0;
        int win1, win2;
        while (i < n) {
            int end1 = f1[i] + t < c1 ? pos1[f1[i] + t] : n;
            int end2 = f2[i] + t < c2 ? pos2[f2[i] + t] : n;
            int nextEnd = min(end1, end2);
            if (nextEnd >= n) {
                continue match;
            }
            i = nextEnd + 1;
            if (end1 < end2) {
                win1++;
            } else {
                win2++;
            }
        }
        if (win1 != win2)
            ans[numOfAns++] = tuple(max(win1, win2), t);
    }

    writeln(numOfAns);
    foreach(x; ans[0..numOfAns]) writeln(x[0], " ", x[1]);
}

import std.stdio;
import std.algorithm;
import std.typecons;

const int MAX = 100005;
int n;
int[MAX] a;
int[MAX] f1, f2, pos1, pos2;
Tuple!(int,int)[MAX] ans;

void main() {
    readf(" %s", n);
    foreach(i; 0..n) readf(" %s", a[i]);

    int c1, c2;
    foreach(i; 0..n) {
        f1[i] = c1-1;
        f2[i] = c2-1;
        if (a[i] == 1) {
            pos1[c1++] = i;
        } else {
            pos2[c2++] = i;
        }
    }

    int numOfAns = 0;

match:
    foreach_reverse(t; 1..n+1) {
        int i = 0;
        int win1, win2;
        while (i < n) {
            int end1 = f1[i] + t < c1 ? pos1[f1[i] + t] : n;
            int end2 = f2[i] + t < c2 ? pos2[f2[i] + t] : n;
            int nextEnd = min(end1, end2);
            if (nextEnd >= n) {
                continue match;
            }
            i = nextEnd + 1;
            if (end1 < end2) {
                win1++;
            } else {
                win2++;
            }
        }
        if ((win1 < win2 && a[n-1] == 2) || (win1 > win2 && a[n-1] == 1))
            ans[numOfAns++] = tuple(max(win1, win2), t);
    }

    writeln(numOfAns);
    foreach(x; ans[0..numOfAns]) writeln(x[0], " ", x[1]);
}

import std.stdio;
import std.uni;
import std.conv;
import std.container;
import std.functional;
import std.algorithm;
import std.array;
import std.typecons;
import std.range;
import std.numeric;
import std.traits;
import std.variant;
import std.concurrency;

void main(string[] args)
{
  auto n = next!int;
  auto a = next!int(n);
  auto pos1 = new int[](n + 1); pos1[] = -1;
  auto pos2 = new int[](n + 1); pos2[] = -1;
  auto cnt1 = new int[](n);
  auto cnt2 = new int[](n);
  foreach(i, ai; a)
    {
      if (i != 0)
	{
	  cnt1[i] = cnt1[i - 1];
	  cnt2[i] = cnt2[i - 1];
	}
      if (ai == 1)
	{
	  cnt1[i]++;
	  pos1[cnt1[i]] = cast(int) i;
	}
      else
	{
	  cnt2[i]++;
	  pos2[cnt2[i]] = cast(int) i;
	}
    }
  foreach(ref c; pos1) if (c == -1) c = n;
  foreach(ref c; pos2) if (c == -1) c = n;
  auto options = new Tuple!(int, int)[](0);
  debug writeln("pos1 = ", pos1);
  debug writeln("pos2 = ", pos2);
 sTest: foreach(s; 1 .. n + 1)
    {
      debug writeln("trying for s = ", s);
      int i = void;
      int ni = void;
      int sets1 = 0;
      int sets2 = 0;
      int next1 = pos1[s];
      int next2 = pos2[s];
      if (next1 < next2)
	{
	  i = next1;
	  sets1++;
	}
      else
	{
	  i = next2;
	  sets2++;
	}
      while (i < n)
	{
	  debug writeln("in i = ", i, " sets1 = ", sets1, " sets2 = ", sets2);
	  if (i == n - 1)
	    {
	      if (sets1 == sets2)
		continue sTest;
	      options ~= tuple(max(sets1, sets2), s);
	      continue sTest;
	    }

	  next1 = (cnt1[i] + s <= n)? pos1[cnt1[i] + s] : n;
	  next2 = (cnt2[i] + s <= n)? pos2[cnt2[i] + s] : n;
	  if (next1 < next2)
	    {
	      ni = next1;
	      sets1++;
	    }
	  else
	    {
	      ni = next2;
	      sets2++;
	    }

	  i = ni;
	}
    }
  auto soptions = sort(options);
  writeln(options.length);
  foreach(option; options)
    {
      writeln(option[0], " ", option[1]);
    }
}

static this()
{
  popChar;
}

struct Any(T)
{
  static auto read()
  {
    static if (is(T == char))
      {
	auto res = frontChar;
	popChar;
	return res;
      }
  }
}

struct Unsigned(T)
{
  auto read()
  {
    auto res = T(0);
    while(!frontChar.isDigit) popChar;
    do
      {
	res = res * T(10) + T(frontChar - '0');
	popChar;
      }
    while(frontChar.isDigit);
    return res;
  }
}

struct Matrix(T, alias rows, alias cols)
{
  T[][] _cell;
  alias _cell this;
  // Ring constructor
  this(int n)
  {
    final switch(n)
      {
      case 0:
	_cell = new T[][](rows, cols);
	break;
      case 1:
	debug assert(rows == cols);
	_cell = new T[][](rows, cols);
	foreach(i; 0 .. rows)
	  _cell[i][i] = T(1);
	break;
      }
  }
  // Copy constructor
  this(Matrix!(T, rows, cols) other)
  {
    _cell = new T[][](rows, cols);
    foreach(i; 0 .. rows)
      _cell[i][] = other[i][];
  }
  auto opBinary(string op)(Matrix!(T, rows, cols) other)
       if (op == "+" || op == "-")
	 {
	   auto res = Matrix!(T, rows, cols)(0);
	   foreach(i; 0 .. rows)
	     foreach(j; 0 .. cols)
	       res[i][j] = mixin(q{this[i][j]}, op, q{other[i][j]});
	   return res;
	 }
  auto opBinary(string op, alias otherRows, alias otherCols)(Matrix!(T, otherRows, otherCols) other)
       if (op == "*")
	 {
	   debug assert(cols == otherRows);
	   auto res = Matrix!(T, rows, otherCols)(0);
	   foreach(i; 0 .. rows)
	     foreach(k; 0 .. cols)
	       foreach(j; 0 .. otherCols)
		 res[i][j] += this[i][k] * other[k][j];
	   return res;
	 }
  ref auto opOpAssign(string op)(Matrix!(T, rows, cols) other)
  {
    static if (op == "*")
      {
	debug assert(rows == cols);
	alias n = rows;
	auto res = Matrix!(T, n, n)(0);
	T factor;
	foreach(i; 0 .. n)
	  foreach(k; 0 .. n)
	    foreach(j; 0 .. n)
	      res[i][j] += this[i][k] * other[k][j];
	foreach(i; 0 .. n)
	  this[i][] = res[i][];
      }
    else
      {
	foreach(i; 0 .. rows)
	  foreach(j; 0 .. cols)
	    mixin(q{this[i][j] }, text(op, q{=}), q{ other[i][j];});
      }
    return this;
  }
  mixin powMethod;
}

struct Mod(T, alias mod)
{
  alias This = Mod!(T, mod);
  T _rep;
  this(T t)
  {
    _rep = t % mod;
    if (_rep < 0) _rep += mod;
  }
  static auto plain(T t)
  {
    auto res = Mod!(T, mod)();
    res._rep = t;
    return res;
  }
  static auto fromPositive(T t)
  {
    pragma(inline, true);
    return Mod!(T, mod).plain(t % mod);
  }
  static auto fromNegative(T t)
  {
    pragma(inline, true);
    return Mod!(T, mod).plain(t % mod + mod);
  }
  string toString()
  {
    return to!string(_rep);
  }
  debug invariant
  {
    assert(_rep >= 0 && _rep < mod);
  }
  auto opBinary(string op)(This b)
  {
    static if (op == "+")
      {
	T resrep = _rep + b._rep;
	if (resrep >= mod) resrep -= mod;
	return This.plain(resrep);
      }
    else static if (op == "-")
      {
	T resrep = _rep - b._rep;
	if (resrep < 0) resrep += mod;
	return This.plain(resrep);
      }
    else static if (op == "*")
      {
	return This.fromPositive(_rep * b._rep);
      }
  }
  auto opOpAssign(string op)(This b)
  {
    mixin(q{_rep }, text(op, "="), q{b._rep;});
    static if (op == "+")
      {
	if (_rep >= mod) _rep -= mod;
      }
    else static if (op == "-")
      {
	if (_rep < 0) _rep += mod;
      }
    else static if (op == "*")
      {
	_rep %= mod;
      }
    return this;
  }

  auto opBinary(string op)(long exp)
       if (op == "^^")
	 {
	   return pow(exp);
	 }
  mixin powMethod;
}

mixin template powMethod()
{
  auto pow(this ThisType)(long exp)
    {
      auto res = ThisType(1);
      auto pow = ThisType(this);
      while(exp)
	{
	  if (exp & 1) res *= pow;
	  pow *= pow;
	  exp >>= 1;
	}
      return res;
    }
}
// INPUT
char frontChar;
void popChar()
{
  import core.stdc.stdio;
  frontChar = cast(char) getchar;
  if (feof(stdin)) frontChar = ' ';
}
auto makeArray(T, S...)(S s)
{
  enum brackets = () {
    string res;
    foreach(i; 0 .. s.length)
      res ~= "[]";
    return res;
  } ();
  mixin(q{alias Type = T}, brackets, q{;});
  return new Type(s);
}
template isNumberLike(T)
{
  enum isNumberLike = is(typeof((){T test; test = test + test * test; test *= test;}()));
}
void popWhite()
{
  import std.ascii;
  while (frontChar.isWhite) popChar;
}
void print(T...)(T t)
{
  static foreach(ti; t)
    {
      static if (is(typeof(ti) == string))
	{
	  write(ti, " ");
	}
      else static if (isArray!(typeof(ti)))
	{
	  foreach(e; ti) print(e);
	}
      else static if (isTuple!(typeof(ti)))
	{
	  static foreach(i; ti.length) writesp(ti[i]);
	}
      else
	{
	  write(ti, " ");
	}
    }
}
void println(T...)(T t)
{
  static if (t.length == 0)
    writeln;
  static foreach(ti; t)
    {
      print(ti);
      writeln;
    }
}
auto next(alias T, S...)(S s)
{
  pragma(inline, true);
  static if (s.length > 0)
    {
      auto res = makeArray!(typeof(next!T()))(s);
      S t;
      enum loops = () {
	string res;
	foreach(i; 0 .. s.length)
	  {
	    auto ti = text(q{t[}, i, q{]});
	    res ~= text(q{for(}, ti, q{ = 0;}, ti , q{ < s[}, i, q{];}, ti, q{++)});
	  }
	return res;
      } ();
      enum indexing = () {
	string res = "res";
	foreach(i; 0 .. s.length)
	  res ~= text(q{[t[}, i, q{]]});
	return res;
      } ();
      mixin(loops, indexing, q{ = next!T;});
      return res;
    }
  else
    {
      static if (isNumberLike!T)
	{
	  import std.ascii: isDigit;
	  T res;
	  while(frontChar.isWhite) popChar;
	  T multiplier = T(1);
	  if (frontChar == '-')
	    {
	      multiplier = T(-1);
	      popChar;
	    }
	  else if (frontChar == '+')
	    {
	      popChar;
	    }
	  debug assert(frontChar.isDigit);
	  do
	    {
	      res = res * T(10) + T(frontChar - '0');
	      popChar;
	    }
	  while(frontChar.isDigit);
	  return multiplier * res;
	}
      else static if (is(T == string))
	{
	  import std.ascii: isWhite;
	  string res;
	  while(frontChar.isWhite)
	    popChar;
	  while(!frontChar.isWhite)
	    {
	      res ~= frontChar;
	      popChar;
	    }
	  return res;
	}
      else static if (is(T == char))
	{
	  while(frontChar.isWhite) popChar;
	  auto res = frontChar;
	  popChar;
	  return res;
	}
      else
	{
	  return T.read;
	}
    }
}

import std.stdio;
import std.uni;
import std.conv;
import std.container;
import std.functional;
import std.algorithm;
import std.array;
import std.typecons;
import std.range;
import std.numeric;
import std.traits;
import std.variant;
import std.concurrency;

void main(string[] args)
{
  auto n = next!int;
  auto a = next!int(n);
  auto pos1 = new int[](n + 1); pos1[] = -1;
  auto pos2 = new int[](n + 1); pos2[] = -1;
  auto cnt1 = new int[](n);
  auto cnt2 = new int[](n);
  foreach(i, ai; a)
    {
      if (i != 0)
	{
	  cnt1[i] = cnt1[i - 1];
	  cnt2[i] = cnt2[i - 1];
	}
      if (ai == 1)
	{
	  cnt1[i]++;
	  pos1[cnt1[i]] = cast(int) i;
	}
      else
	{
	  cnt2[i]++;
	  pos2[cnt2[i]] = cast(int) i;
	}
    }
  foreach(ref c; pos1) if (c == -1) c = n;
  foreach(ref c; pos2) if (c == -1) c = n;
  auto options = new Tuple!(int, int)[](0);
  debug writeln("pos1 = ", pos1);
  debug writeln("pos2 = ", pos2);
 sTest: foreach(s; 1 .. n + 1)
    {
      debug writeln("trying for s = ", s);
      int i = void;
      int ni = void;
      int sets1 = 0;
      int sets2 = 0;
      int next1 = pos1[s];
      int next2 = pos2[s];
      if (next1 < next2)
	{
	  i = next1;
	  sets1++;
	}
      else
	{
	  i = next2;
	  sets2++;
	}
      while (i < n)
	{
	  debug writeln("in i = ", i, " sets1 = ", sets1, " sets2 = ", sets2);
	  if (i == n - 1)
	    {
	      if (sets1 == sets2)
		continue sTest;
	      options ~= tuple(s, max(sets1, sets2));
	      continue sTest;
	    }

	  next1 = (cnt1[i] + s <= n)? pos1[cnt1[i] + s] : n;
	  next2 = (cnt2[i] + s <= n)? pos2[cnt2[i] + s] : n;
	  if (next1 < next2)
	    {
	      ni = next1;
	      sets1++;
	    }
	  else
	    {
	      ni = next2;
	      sets2++;
	    }

	  i = ni;
	}
    }
  writeln(options.length);
  foreach(option; options)
    {
      writeln(option[0], " ", option[1]);
    }
}

static this()
{
  popChar;
}

struct Any(T)
{
  static auto read()
  {
    static if (is(T == char))
      {
	auto res = frontChar;
	popChar;
	return res;
      }
  }
}

struct Unsigned(T)
{
  auto read()
  {
    auto res = T(0);
    while(!frontChar.isDigit) popChar;
    do
      {
	res = res * T(10) + T(frontChar - '0');
	popChar;
      }
    while(frontChar.isDigit);
    return res;
  }
}

struct Matrix(T, alias rows, alias cols)
{
  T[][] _cell;
  alias _cell this;
  // Ring constructor
  this(int n)
  {
    final switch(n)
      {
      case 0:
	_cell = new T[][](rows, cols);
	break;
      case 1:
	debug assert(rows == cols);
	_cell = new T[][](rows, cols);
	foreach(i; 0 .. rows)
	  _cell[i][i] = T(1);
	break;
      }
  }
  // Copy constructor
  this(Matrix!(T, rows, cols) other)
  {
    _cell = new T[][](rows, cols);
    foreach(i; 0 .. rows)
      _cell[i][] = other[i][];
  }
  auto opBinary(string op)(Matrix!(T, rows, cols) other)
       if (op == "+" || op == "-")
	 {
	   auto res = Matrix!(T, rows, cols)(0);
	   foreach(i; 0 .. rows)
	     foreach(j; 0 .. cols)
	       res[i][j] = mixin(q{this[i][j]}, op, q{other[i][j]});
	   return res;
	 }
  auto opBinary(string op, alias otherRows, alias otherCols)(Matrix!(T, otherRows, otherCols) other)
       if (op == "*")
	 {
	   debug assert(cols == otherRows);
	   auto res = Matrix!(T, rows, otherCols)(0);
	   foreach(i; 0 .. rows)
	     foreach(k; 0 .. cols)
	       foreach(j; 0 .. otherCols)
		 res[i][j] += this[i][k] * other[k][j];
	   return res;
	 }
  ref auto opOpAssign(string op)(Matrix!(T, rows, cols) other)
  {
    static if (op == "*")
      {
	debug assert(rows == cols);
	alias n = rows;
	auto res = Matrix!(T, n, n)(0);
	T factor;
	foreach(i; 0 .. n)
	  foreach(k; 0 .. n)
	    foreach(j; 0 .. n)
	      res[i][j] += this[i][k] * other[k][j];
	foreach(i; 0 .. n)
	  this[i][] = res[i][];
      }
    else
      {
	foreach(i; 0 .. rows)
	  foreach(j; 0 .. cols)
	    mixin(q{this[i][j] }, text(op, q{=}), q{ other[i][j];});
      }
    return this;
  }
  mixin powMethod;
}

struct Mod(T, alias mod)
{
  alias This = Mod!(T, mod);
  T _rep;
  this(T t)
  {
    _rep = t % mod;
    if (_rep < 0) _rep += mod;
  }
  static auto plain(T t)
  {
    auto res = Mod!(T, mod)();
    res._rep = t;
    return res;
  }
  static auto fromPositive(T t)
  {
    pragma(inline, true);
    return Mod!(T, mod).plain(t % mod);
  }
  static auto fromNegative(T t)
  {
    pragma(inline, true);
    return Mod!(T, mod).plain(t % mod + mod);
  }
  string toString()
  {
    return to!string(_rep);
  }
  debug invariant
  {
    assert(_rep >= 0 && _rep < mod);
  }
  auto opBinary(string op)(This b)
  {
    static if (op == "+")
      {
	T resrep = _rep + b._rep;
	if (resrep >= mod) resrep -= mod;
	return This.plain(resrep);
      }
    else static if (op == "-")
      {
	T resrep = _rep - b._rep;
	if (resrep < 0) resrep += mod;
	return This.plain(resrep);
      }
    else static if (op == "*")
      {
	return This.fromPositive(_rep * b._rep);
      }
  }
  auto opOpAssign(string op)(This b)
  {
    mixin(q{_rep }, text(op, "="), q{b._rep;});
    static if (op == "+")
      {
	if (_rep >= mod) _rep -= mod;
      }
    else static if (op == "-")
      {
	if (_rep < 0) _rep += mod;
      }
    else static if (op == "*")
      {
	_rep %= mod;
      }
    return this;
  }

  auto opBinary(string op)(long exp)
       if (op == "^^")
	 {
	   return pow(exp);
	 }
  mixin powMethod;
}

mixin template powMethod()
{
  auto pow(this ThisType)(long exp)
    {
      auto res = ThisType(1);
      auto pow = ThisType(this);
      while(exp)
	{
	  if (exp & 1) res *= pow;
	  pow *= pow;
	  exp >>= 1;
	}
      return res;
    }
}
// INPUT
char frontChar;
void popChar()
{
  import core.stdc.stdio;
  frontChar = cast(char) getchar;
  if (feof(stdin)) frontChar = ' ';
}
auto makeArray(T, S...)(S s)
{
  enum brackets = () {
    string res;
    foreach(i; 0 .. s.length)
      res ~= "[]";
    return res;
  } ();
  mixin(q{alias Type = T}, brackets, q{;});
  return new Type(s);
}
template isNumberLike(T)
{
  enum isNumberLike = is(typeof((){T test; test = test + test * test; test *= test;}()));
}
void popWhite()
{
  import std.ascii;
  while (frontChar.isWhite) popChar;
}
void print(T...)(T t)
{
  static foreach(ti; t)
    {
      static if (is(typeof(ti) == string))
	{
	  write(ti, " ");
	}
      else static if (isArray!(typeof(ti)))
	{
	  foreach(e; ti) print(e);
	}
      else static if (isTuple!(typeof(ti)))
	{
	  static foreach(i; ti.length) writesp(ti[i]);
	}
      else
	{
	  write(ti, " ");
	}
    }
}
void println(T...)(T t)
{
  static if (t.length == 0)
    writeln;
  static foreach(ti; t)
    {
      print(ti);
      writeln;
    }
}
auto next(alias T, S...)(S s)
{
  pragma(inline, true);
  static if (s.length > 0)
    {
      auto res = makeArray!(typeof(next!T()))(s);
      S t;
      enum loops = () {
	string res;
	foreach(i; 0 .. s.length)
	  {
	    auto ti = text(q{t[}, i, q{]});
	    res ~= text(q{for(}, ti, q{ = 0;}, ti , q{ < s[}, i, q{];}, ti, q{++)});
	  }
	return res;
      } ();
      enum indexing = () {
	string res = "res";
	foreach(i; 0 .. s.length)
	  res ~= text(q{[t[}, i, q{]]});
	return res;
      } ();
      mixin(loops, indexing, q{ = next!T;});
      return res;
    }
  else
    {
      static if (isNumberLike!T)
	{
	  import std.ascii: isDigit;
	  T res;
	  while(frontChar.isWhite) popChar;
	  T multiplier = T(1);
	  if (frontChar == '-')
	    {
	      multiplier = T(-1);
	      popChar;
	    }
	  else if (frontChar == '+')
	    {
	      popChar;
	    }
	  debug assert(frontChar.isDigit);
	  do
	    {
	      res = res * T(10) + T(frontChar - '0');
	      popChar;
	    }
	  while(frontChar.isDigit);
	  return multiplier * res;
	}
      else static if (is(T == string))
	{
	  import std.ascii: isWhite;
	  string res;
	  while(frontChar.isWhite)
	    popChar;
	  while(!frontChar.isWhite)
	    {
	      res ~= frontChar;
	      popChar;
	    }
	  return res;
	}
      else static if (is(T == char))
	{
	  while(frontChar.isWhite) popChar;
	  auto res = frontChar;
	  popChar;
	  return res;
	}
      else
	{
	  return T.read;
	}
    }
}


import core.bitop;
import core.checkedint;
//import core.stdc.stdio;
import core.stdc.stdlib: alloca, malloc, calloc, realloc, _Exit;
import core.stdc.string;
import std.algorithm;
import std.array;
import std.ascii;
import std.bigint;
import std.bitmanip;
import std.container;
import std.conv;
import std.exception;
import std.functional;
import std.math;
import std.meta;
import std.numeric;
import std.random;
import std.range;
import std.regex;
import std.stdio;
import std.string;
import std.typecons;

__gshared:

alias BitSet(size_t n) = size_t[(n + size_t.sizeof * 8 - 1) / (size_t.sizeof * 8)];

auto getAddrTuple() {
    return tuple();
}

auto getAddrTuple(T, U...)(ref T head, ref U tail) {
    return tuple(&head, getAddrTuple(tail).expand);
}

bool read(T...)(ref T vars) if (vars.length > 0) {
    enum spec = ' ' ~ replicate("%s ", vars.length);
    return readf(spec, getAddrTuple(vars).expand) == vars.length;
}

void memSet(T, size_t n)(ref T[n] a, ubyte value) {
    memset(a.ptr, value, a.sizeof);
}

void memSet(T)(T[ ] a, ubyte value) {
    memset(a.ptr, value, a.length * T.sizeof);
}

auto pairwise(R)(R range) if (isForwardRange!R) {
    return lockstep(range, dropOne(range));
}

struct Problem {
    int id, limit, time;

    int opCmp(Problem rhs) const {
        return tuple(time, limit).opCmp(tuple(rhs.time, rhs.limit));
    }
}

int n, total;
Problem[200_000] _problems;
Problem[ ] problems;
RedBlackTree!(Problem, q{a.id < b.id})[200_000] _solvedDist;
RedBlackTree!(Problem, q{a.id < b.id})[ ] solvedDist;
int curCount, bestCount;
RedBlackTree!(Problem, q{a < b}, true) solved;

void run(alias callback)() {
    generate!(redBlackTree!(q{a.id < b.id}, Problem)).take(n).copy(solvedDist);
    int curTime = 0;
    curCount = 0;
    auto solvable = redBlackTree!true(problems);
    solved = redBlackTree!(true, Problem);
    foreach (c; 1 .. n + 1) {
        while (!solved.empty && !solvable.empty && solvable.front.time < solved.front.time) {
            const a = solvable.front;
            solvable.removeFront();
            if (c <= a.limit) {
                const b = solved.front;
                solved.removeFront();
                solvedDist[b.limit - 1].removeKey(b);
                curTime -= b.time - a.time;
                solved.insert(a);
                solvedDist[a.limit - 1].insert(a);
                if (c <= b.limit)
                    solvable.insert(b);
            }
        }
        while (solved.length < c && !solvable.empty && curTime + solvable.front.time <= total) {
            const a = solvable.front;
            solvable.removeFront();
            if (c <= a.limit) {
                curTime += a.time;
                curCount++;
                solved.insert(a);
                solvedDist[a.limit - 1].insert(a);
                if (callback())
                    return;
            }
        }
        foreach (p; solvedDist[c - 1]) {
            assert(p.limit == c);
            solved.removeKey(p);
            curTime -= p.time;
            curCount--;
        }
        solvedDist[c - 1] = null;
    }
}

void main() {
    while (read(n, total)) {
        problems = _problems[0 .. n];
        solvedDist = _solvedDist[0 .. n];
        foreach (int i, ref p; problems) {
            p.id = i + 1;
            read(p.limit, p.time);
        }

        problems.multiSort!(q{a.limit < b.limit}, q{a.time < b.time});
        bestCount = 0;
        run!({
            if (curCount > bestCount)
                bestCount = curCount;
            return false;
        });

        writeln(bestCount, '\n', bestCount);
        run!({
            if (curCount != bestCount)
                return false;
            writefln("%(%s %)", solved[ ].map!q{a.id});
            return true;
        });
        debug writeln();
    }

    stdout.flush();
    _Exit(0);
}

import core.bitop, std.algorithm, std.bigint, std.bitmanip, std.complex,
	std.container, std.conv, std.datetime, std.functional, std.math, std.meta;
import std.numeric : Fft, fft, gcd, inverseFft;
import std.parallelism, std.random, std.range, std.regex, std.stdio, std.string,
	std.traits, std.typecons, std.uni, std.variant;

alias pair(X, Y) = Tuple!(X, "fi", Y, "se");
alias mp = make_pair;
alias pii = pair!(int, int);
alias pll = pair!(long, long);
// alias gcd = std.numeric.gcd;
alias lint = long;
alias rbt = RedBlackTree;
/// struct vector as c++ vector
struct Vec(T)
{
	private Array!T buf;
	alias buf this;
	this(this)
	{
		buf = buf.dup;
	}
	/// construct from length
	this(U)(U length)
			if (is(U == int) || is(U == size_t) || is(U == long) || is(U == ulong) || is(U == uint))
	{
		buf.length = length;
	}
	/// construct from length and default value
	this(U, X)(U length, X val)
			if (isImplicitlyConvertible!(X, T) || (is(U == int)
				|| is(U == size_t) || is(U == long) || is(U == ulong) || is(U == uint)))
	{
		buf.length = length;
		foreach (ref x; buf[])
		{
			x = val;
		}
	}
	/// construct from other array
	this(U)(U[] values...) if (isImplicitlyConvertible!(U, T))
	{
		buf = Array!(T)(values);
	}
	/// construct from other range
	this(Range)(Range r)
			if (isInputRange!Range && isImplicitlyConvertible!(ElementType!Range,
				T) && !is(Range == T[]))
	{
		buf = Array!(T)(r);
	}
	/// integer length
	int size() @property const
	{
		return cast(int) buf.length;
	}
}
///modulo
enum mm = 10 ^^ 9 + 7, mm2 = mm + 2;
public
{
	pure nothrow
	{
		///lcm
		T lcm(T)(auto ref T a, auto ref T b)
		{
			return a / gcd(a, b) * b;
		}
		///make_pair
		pair!(X, Y) make_pair(X, Y)(in X x_, in Y y_)
		{
			return tuple!(X, "fi", Y, "se")(x_, y_);
		}
		///BigInt greatest common divizor
		BigInt biggcd(BigInt a, BigInt b)
		{
			BigInt res = 1;
			while (b)
			{
				if ((a & 1) && (b & 1))
				{
					a -= b;
					a >>= 1;
				}
				else if (a & 1)
				{
					b >>= 1;
				}
				else if (b & 1)
				{
					a >>= 1;
				}
				else
				{
					res <<= 1;
					a >>= 1;
					b >>= 1;
				}
				if (a < b)
					swap(a, b);
			}
			return res * a;
		}
		///square
		@property X sqr(X)(in X a_)
		{
			return a_ * a_;
		}
		///cube
		@property X cub(X)(in X a_)
		{
			return a_ * a_ * a_;
		}
		///posicion lower bound
		size_t lowb(T, X)(T a, auto ref X g)
				if (isRandomAccessRange!T && hasLength!T && is(typeof(g < a[0]) == bool))
		{
			return assumeSorted(a).lowerBound(g).length;
		}
		///posicion upper bound
		size_t upb(T, X)(T a, auto ref X g)
				if (isRandomAccessRange!T && hasLength!T && is(typeof(g < a[0]) == bool))
		{
			return a.length - assumeSorted(a).upperBound(g).length;
		}
		///posicion binary search
		size_t binf(T, X)(T a, auto ref X g)
				if (isRandomAccessRange!T && hasLength!T && is(typeof(g < a[0]) == bool))
		{
			auto pos = lowb(a, g);
			return (g == a[pos]) ? pos : a.length;
		}
		///binary search
		bool binary_search(T, X)(T a, auto ref X g)
				if (isRandomAccessRange!T && hasLength!T && is(typeof(g < a[0]) == bool))
		{
			return assumeSorted(a).contains(g);
		}
	}
	///write an array
	void putarr(X)(in X a, in char ch = ' ') if (isInputRange!X)
	{
		writefln("%(%s" ~ ch ~ "%)", a);
	}
	///write a matrix
	void putarr(X)(in X a)
			if (isInputRange!X && isInputRange!(ElementType!X) && !isSomeString!(ElementType!X))
	{
		writefln("%(%(%s %)\n%)", a);
	}
	///get an array
	bool getarr(X)(X a, in size_t n)
	{
		bool b = 1;
		foreach (ref i; a[0 .. n])
			b = input(&i);
		return b;
	}
	///read without format
	bool input(T...)(auto ref T ptrs) if (ptrs.length > 0)
	{
		return readf!(replicate(" %s", ptrs.length))(ptrs) == ptrs.length;
	}
	///readln without format
	bool read(T...)(auto ref T ptrs) if (ptrs.length > 0)
	{
		const bool fl = readf!(replicate(" %s", ptrs.length))(ptrs) == ptrs.length;
		readln;
		return fl;
	}
	///opening file
	nothrow auto inf(in char* name)
	{
		return freopen(name, "r", core.stdc.stdio.stdin);
	}
	///closing file
	nothrow auto ouf(in char* name)
	{
		return freopen(name, "w", core.stdc.stdio.stdout);
	}
	///parsing array from line
	@property auto arread(T)()
	{
		return readln.splitter.map!(to!(T)).array;
	}
	///outbuffer
	void enter(T...)(T args)
	{
		writeln(args);
		stdout.flush;
	}
}
//foreach_reverse isAlpha isNumber isWhite isLower isUpper toLower toUpper mixin
//cumulativeFold return static heapify join filter foreach
//------------------------------------------program beginning--------------------------

void main()
{
	int n, T;
	read(n, T);
	auto a = new Tuple!(int, int, int)[n];
	foreach (i; 0 .. n)
	{
		read(a[i][0], a[i][1]);
		a[i][2] = i + 1;
	}
	sort!"a[1]<b[1]"(a);
	bool check(int k)
	{
		int c;
		long curt;
		foreach (x; a)
		{
			if (c == k)
				break;
			if (x[0] < k)
				continue;
			c++;
			curt += x[1];
		}
		return c == k && curt <= T;
	}

	int l = 0, r = n;
	while (l < r)
	{
		int m = (l + r + 1) / 2;
		if (check(m))
			l = m;
		else
			r = m - 1;
	}
	int[] ans;
	foreach (x; a)
	{
		if (ans.length == l)
			break;
		if (x[0] < l)
			continue;
		ans ~= x[2];
	}
	writeln(l, '\n', l);
	putarr(ans, ' ');
}

import std.stdio, std.array, std.string, std.conv, std.algorithm;
import std.typecons, std.range, std.random, std.math, std.container;
import std.numeric, std.bigint, core.bitop;

alias Problem = Tuple!(int, "num", long, "time", int, "index");

void main() {
    auto s = readln.split.map!(to!int);
    auto N = s[0];
    auto T = s[1].to!long;
    auto P = new Problem[](N);
    foreach (i; 0..N) {
        s = readln.split.map!(to!int);
        P[i] = tuple(s[0], s[1].to!long, i+1);
    }
    P.sort!"a[1] < b[1]";

    int hi = N+1;
    int lo = 0;
    while (hi - lo > 1) {
        int mid = (hi + lo) / 2;
        long tmp = 0;
        int cnt = 0;
        foreach (p; P) {
            if (p.num < mid) continue;
            tmp += p.time;
            cnt += 1;
            if (cnt >= mid) break;
        }
        if (cnt >= mid && tmp <= T) {
            lo = mid;
        } else {
            hi = mid;
        }
    }

    int[] ans;
    int cnt = 0;
    foreach (p; P) {
        if (p.num >= lo) {
            ans ~= p.index;
            cnt += 1;
        }
        if (cnt >= lo) break;
    }

    lo.writeln;
    lo.writeln;
    if (lo == 0) writeln;
    else ans.map!(to!string).join(" ").writeln;
}

import core.bitop, std.algorithm, std.bigint, std.bitmanip, std.complex,
	std.container, std.conv, std.datetime, std.functional, std.math, std.meta;
import std.numeric : Fft, fft, gcd, inverseFft;
import std.parallelism, std.random, std.range, std.regex, std.stdio, std.string,
	std.traits, std.typecons, std.uni, std.variant;

alias pair(X, Y) = Tuple!(X, "fi", Y, "se");
alias mp = make_pair;
alias pii = pair!(int, int);
alias pll = pair!(long, long);
// alias gcd = std.numeric.gcd;
alias lint = long;
alias rbt = RedBlackTree;
/// struct vector as c++ vector
struct Vec(T)
{
	private Array!T buf;
	alias buf this;
	this(this)
	{
		buf = buf.dup;
	}
	/// construct from length
	this(U)(U length)
			if (is(U == int) || is(U == size_t) || is(U == long) || is(U == ulong) || is(U == uint))
	{
		buf.length = length;
	}
	/// construct from length and default value
	this(U, X)(U length, X val)
			if (isImplicitlyConvertible!(X, T) || (is(U == int)
				|| is(U == size_t) || is(U == long) || is(U == ulong) || is(U == uint)))
	{
		buf.length = length;
		foreach (ref x; buf[])
		{
			x = val;
		}
	}
	/// construct from other array
	this(U)(U[] values...) if (isImplicitlyConvertible!(U, T))
	{
		buf = Array!(T)(values);
	}
	/// construct from other range
	this(Range)(Range r)
			if (isInputRange!Range && isImplicitlyConvertible!(ElementType!Range,
				T) && !is(Range == T[]))
	{
		buf = Array!(T)(r);
	}
	/// integer length
	int size() @property const
	{
		return cast(int) buf.length;
	}
}
///modulo
enum mm = 10 ^^ 9 + 7, mm2 = mm + 2;
public
{
	pure nothrow
	{
		///lcm
		T lcm(T)(auto ref T a, auto ref T b)
		{
			return a / gcd(a, b) * b;
		}
		///make_pair
		pair!(X, Y) make_pair(X, Y)(in X x_, in Y y_)
		{
			return tuple!(X, "fi", Y, "se")(x_, y_);
		}
		///BigInt greatest common divizor
		BigInt biggcd(BigInt a, BigInt b)
		{
			BigInt res = 1;
			while (b)
			{
				if ((a & 1) && (b & 1))
				{
					a -= b;
					a >>= 1;
				}
				else if (a & 1)
				{
					b >>= 1;
				}
				else if (b & 1)
				{
					a >>= 1;
				}
				else
				{
					res <<= 1;
					a >>= 1;
					b >>= 1;
				}
				if (a < b)
					swap(a, b);
			}
			return res * a;
		}
		///square
		@property X sqr(X)(in X a_)
		{
			return a_ * a_;
		}
		///cube
		@property X cub(X)(in X a_)
		{
			return a_ * a_ * a_;
		}
		///posicion lower bound
		size_t lowb(T, X)(T a, auto ref X g)
				if (isRandomAccessRange!T && hasLength!T && is(typeof(g < a[0]) == bool))
		{
			return assumeSorted(a).lowerBound(g).length;
		}
		///posicion upper bound
		size_t upb(T, X)(T a, auto ref X g)
				if (isRandomAccessRange!T && hasLength!T && is(typeof(g < a[0]) == bool))
		{
			return a.length - assumeSorted(a).upperBound(g).length;
		}
		///posicion binary search
		size_t binf(T, X)(T a, auto ref X g)
				if (isRandomAccessRange!T && hasLength!T && is(typeof(g < a[0]) == bool))
		{
			auto pos = lowb(a, g);
			return (g == a[pos]) ? pos : a.length;
		}
		///binary search
		bool binary_search(T, X)(T a, auto ref X g)
				if (isRandomAccessRange!T && hasLength!T && is(typeof(g < a[0]) == bool))
		{
			return assumeSorted(a).contains(g);
		}
	}
	///write an array
	void putarr(X)(in X a, in char ch = ' ') if (isInputRange!X)
	{
		writefln("%(%s" ~ ch ~ "%)", a);
	}
	///write a matrix
	void putarr(X)(in X a)
			if (isInputRange!X && isInputRange!(ElementType!X) && !isSomeString!(ElementType!X))
	{
		writefln("%(%(%s %)\n%)", a);
	}
	///get an array
	bool getarr(X)(X a, in size_t n)
	{
		bool b = 1;
		foreach (ref i; a[0 .. n])
			b = input(&i);
		return b;
	}
	///read without format
	bool input(T...)(auto ref T ptrs) if (ptrs.length > 0)
	{
		return readf!(replicate(" %s", ptrs.length))(ptrs) == ptrs.length;
	}
	///readln without format
	bool read(T...)(auto ref T ptrs) if (ptrs.length > 0)
	{
		const bool fl = readf!(replicate(" %s", ptrs.length))(ptrs) == ptrs.length;
		readln;
		return fl;
	}
	///opening file
	nothrow auto inf(in char* name)
	{
		return freopen(name, "r", core.stdc.stdio.stdin);
	}
	///closing file
	nothrow auto ouf(in char* name)
	{
		return freopen(name, "w", core.stdc.stdio.stdout);
	}
	///parsing array from line
	@property auto arread(T)()
	{
		return readln.splitter.map!(to!(T)).array;
	}
	///outbuffer
	void enter(T...)(T args)
	{
		writeln(args);
		stdout.flush;
	}
}
//foreach_reverse isAlpha isNumber isWhite isLower isUpper toLower toUpper mixin
//cumulativeFold return static heapify join filter foreach
//------------------------------------------program beginning--------------------------

void main()
{
	int n, T;
	read(n, T);
	auto a = new Tuple!(int, int, int)[n];
	foreach (i; 0 .. n)
	{
		read(a[i][0], a[i][1]);
		a[i][2] = i + 1;
	}
	sort!"a[1]<b[1]"(a);
	bool check(int k)
	{
		int c;
		long curt;
		foreach (x; a)
		{
			if (c == k)
				break;
			if (x[0] < k)
				continue;
			c++;
			curt += x[1];
		}
		return curt <= T;
	}

	int l = 0, r = n;
	while (l < r)
	{
		int m = (l + r + 1) / 2;
		if (check(m))
			l = m;
		else
			r = m - 1;
	}
	int[] ans;
	foreach (x; a)
	{
		if (ans.length == l)
			break;
		if (x[0] < l)
			continue;
		ans ~= x[2];
	}
	writeln(l, '\n', l);
	putarr(ans, ' ');
}

import std.stdio, std.array, std.string, std.conv, std.algorithm;
import std.typecons, std.range, std.random, std.math, std.container;
import std.numeric, std.bigint, core.bitop;

alias Problem = Tuple!(int, "num", long, "time", int, "index");

void main() {
    auto s = readln.split.map!(to!int);
    auto N = s[0];
    auto T = s[1].to!long;
    auto P = new Problem[](N);
    foreach (i; 0..N) {
        s = readln.split.map!(to!int);
        P[i] = tuple(s[0], s[1].to!long, i+1);
    }
    P.sort!"a[1] < b[1]";

    int hi = N+1;
    int lo = 0;
    while (hi - lo > 1) {
        int mid = (hi + lo) / 2;
        long tmp = 0;
        int cnt = 0;
        foreach (p; P) {
            if (p.num < mid) continue;
            tmp += p.time;
            cnt += 1;
            if (cnt >= mid) break;
        }
        if (cnt >= mid && tmp <= T) {
            lo = mid;
        } else {
            hi = mid;
        }
    }

    int[] ans;
    foreach (i; 0..lo) if (P[i].num >= lo) ans ~= P[i].index;
    lo.writeln;
    lo.writeln;
    ans.map!(to!string).join(" ").writeln;
}

import core.bitop;
import core.checkedint;
//import core.stdc.stdio;
import core.stdc.stdlib: alloca, malloc, calloc, realloc, _Exit;
import core.stdc.string;
import std.algorithm;
import std.array;
import std.ascii;
import std.bigint;
import std.bitmanip;
import std.container;
import std.conv;
import std.exception;
import std.functional;
import std.math;
import std.meta;
import std.numeric;
import std.random;
import std.range;
import std.regex;
import std.stdio;
import std.string;
import std.typecons;

__gshared:

alias BitSet(size_t n) = size_t[(n + size_t.sizeof * 8 - 1) / (size_t.sizeof * 8)];

auto getAddrTuple() {
    return tuple();
}

auto getAddrTuple(T, U...)(ref T head, ref U tail) {
    return tuple(&head, getAddrTuple(tail).expand);
}

bool read(T...)(ref T vars) if (vars.length > 0) {
    enum spec = ' ' ~ replicate("%s ", vars.length);
    return readf(spec, getAddrTuple(vars).expand) == vars.length;
}

void memSet(T, size_t n)(ref T[n] a, ubyte value) {
    memset(a.ptr, value, a.sizeof);
}

void memSet(T)(T[ ] a, ubyte value) {
    memset(a.ptr, value, a.length * T.sizeof);
}

auto pairwise(R)(R range) if (isForwardRange!R) {
    return lockstep(range, dropOne(range));
}

struct Problem {
    int id, limit, time;

    int opCmp(Problem rhs) const {
        return tuple(time, limit).opCmp(tuple(rhs.time, rhs.limit));
    }
}

Problem[200_000] _problems;
RedBlackTree!(Problem, q{a.id < b.id})[200_000] _solvedDist;

void main() {
    int n, total;
    while (read(n, total)) {
        auto problems = _problems[0 .. n];
        auto solvedDist = _solvedDist[0 .. n];
        foreach (int i, ref p; problems) {
            p.id = i + 1;
            read(p.limit, p.time);
        }

        problems.multiSort!(q{a.limit < b.limit}, q{a.time < b.time});
        generate!(redBlackTree!(q{a.id < b.id}, Problem)).take(n).copy(solvedDist);
        int bestTime = 10^^9 + 1, bestCount = 0;
        int curTime = 0, curCount = 0;
        auto solvable = redBlackTree!(true, Problem);
        auto solved = redBlackTree!(true, Problem);
        int pLastIndex = 0;
        foreach (c; 1 .. n + 1) {
            for (; pLastIndex < n && problems[pLastIndex].limit <= c; pLastIndex++)
                solvable.insert(problems[pLastIndex]);
            while (!solved.empty && !solvable.empty && solvable.front.time < solved.front.time) {
                const a = solvable.front;
                solvable.removeFront();
                if (c <= a.limit) {
                    const b = solved.front;
                    solved.removeFront();
                    solvedDist[b.limit - 1].removeKey(b);
                    curTime -= b.time - a.time;
                    solved.insert(a);
                    solvedDist[a.limit - 1].insert(a);
                    if (c <= b.limit)
                        solvable.insert(b);
                }
            }
            while (solved.length < c && !solvable.empty && curTime + solvable.front.time <= total) {
                const a = solvable.front;
                solvable.removeFront();
                if (c <= a.limit) {
                    curTime += a.time;
                    curCount++;
                    solved.insert(a);
                    solvedDist[a.limit - 1].insert(a);
                    if (curCount > bestCount) {
                        bestTime = curTime;
                        bestCount = curCount;
                    }
                }
            }
            foreach (p; solvedDist[c - 1]) {
                assert(p.limit == c);
                solved.removeKey(p);
                curTime -= p.time;
                curCount--;
            }
            solvedDist[c - 1] = null;
        }

        writeln(bestCount, '\n', bestCount);
        generate!(redBlackTree!(q{a.id < b.id}, Problem)).take(n).copy(solvedDist);
        curTime = 0;
        curCount = 0;
        solvable.clear();
        solved.clear();
        pLastIndex = 0;
    restoreResult:
        foreach (c; 1 .. n + 1) {
            for (; pLastIndex < n && problems[pLastIndex].limit <= c; pLastIndex++)
                solvable.insert(problems[pLastIndex]);
            while (!solved.empty && !solvable.empty && solvable.front.time < solved.front.time) {
                const a = solvable.front;
                solvable.removeFront();
                if (c <= a.limit) {
                    const b = solved.front;
                    solved.removeFront();
                    solvedDist[b.limit - 1].removeKey(b);
                    curTime -= b.time - a.time;
                    solved.insert(a);
                    solvedDist[a.limit - 1].insert(a);
                    if (c <= b.limit)
                        solvable.insert(b);
                }
            }
            while (solved.length < c && !solvable.empty && curTime + solvable.front.time <= total) {
                const a = solvable.front;
                solvable.removeFront();
                if (c <= a.limit) {
                    curTime += a.time;
                    curCount++;
                    solved.insert(a);
                    solvedDist[a.limit - 1].insert(a);
                    if (curCount == bestCount) {
                        writefln("%(%s %)", solved[ ].map!q{a.id});
                        break restoreResult;
                    }
                }
            }
            foreach (p; solvedDist[c - 1]) {
                assert(p.limit == c);
                solved.removeKey(p);
                curTime -= p.time;
                curCount--;
            }
            solvedDist[c - 1] = null;
        }
        debug writeln();
    }

    stdout.flush();
    _Exit(0);
}


import std.algorithm;
import std.conv;
import std.range;
import std.stdio;
import std.string;

void main ()
{
	int n, q;
	while (readf !(" %s %s") (n, q) > 0)
	{
		readln;
		auto s = ['x', 'x'] ~ readln.strip.dup ~ ['x', 'x'];
		auto cur = s.count ("abc");
		foreach (j; 0..q)
		{
			int i;
			char ch;
			readf !(" %s %s") (i, ch);
			i += 1;
			cur -= (s[i - 2..i + 1] == "abc");
			cur -= (s[i - 1..i + 2] == "abc");
			cur -= (s[i - 0..i + 3] == "abc");
			s[i] = ch;
			cur += (s[i - 2..i + 1] == "abc");
			cur += (s[i - 1..i + 2] == "abc");
			cur += (s[i - 0..i + 3] == "abc");
			writeln (cur);
		}
	}
}

immutable multi = false;

void solve(int tc)
{
  auto n = readInt!int;
  auto q = readInt!int;
  auto s = cast(char[])readString;
  auto cnt = new int[](n);
  int sm;
  int isAbc(int i)
  {
    if (i + 3 > n) return 0;
    return int(s[i .. i + 3] == "abc");
  }
  foreach(i, ref ci; cnt)
    {
      ci = isAbc(cast(int)i);
    }
  sm = cnt.sum;
  void reCalc(int i)
  {
    if (i < 0 || i >= n) return;
    auto ld = cnt[i];
    auto nw = isAbc(i);
    auto dlt = nw - ld;
    cnt[i] = nw;
    sm += dlt;
  }
  foreach(qi; 0 .. q)
    {
      auto pos = readInt!int - 1;
      auto cString = readString;
      auto c = cString[0];
      s[pos] = c;
      foreach(p; pos - 3 .. pos + 1)
	{
	  reCalc(p);
	}
      sm.writeln;
    }
}

// main {{{
void main()
{
	auto t = multi? readInt!int : 1;
	foreach(tc; 0 .. t) solve(tc);
}
// }}}
// input {{{
int currChar;
static this()
{
	currChar = ' ';
}

char topChar()
{
	return cast(char) currChar;
}

void popChar()
{
	import core.stdc.stdio;
	currChar = getchar();
}

auto readInt(T)()
{
	T num = 0;
	int sgn = 0;
	while (topChar.isWhite)
		popChar;
	while (topChar == '-' || topChar == '+')
	{
		sgn ^= (topChar == '-');
		popChar;
	}
	while (topChar.isDigit)
	{
		num *= 10;
		num += (topChar - '0');
		popChar;
	}
	if (sgn)
		return -num;
	return num;
}

string readString()
{
	string res = "";
	while (topChar.isWhite)
		popChar;
	while (!topChar.isWhite)
	{
		res ~= topChar;
		popChar;
	}
	return res;
}
void writes(T...)(T t)
{
	static foreach(i, ti; t)
	{
		static if (isIterable!(T[i]))
		{
			foreach(e; ti)
			{
				write(e, " ");
			}
		}
	}
}
auto ra(V)()
{
	int n = readInt!int;
	return ma(n, readInt!V);
}
auto rt(V)()
{
	int n = readInt!int;
	int m = readInt!int;
	return ma(n, ma(m, readInt!V));
}
auto rbg()
{
	int n = readInt!int;
	int m = readInt!int;
	auto adj = new int[][](n);
	foreach(i; 0 .. m)
	{
		auto u = readInt!int - 1;
		auto v = readInt!int - 1;
		adj[u] ~= v;
		adj[v] ~= u;
	}
	return adj;
}
auto ma(V)(size_t n, lazy V v)
{
	auto arr = new V[](n);
	foreach(ref ai; arr) ai = v;
	return arr;
}
// }}}
// imports {{{
import std.stdio;
import std.algorithm;
import std.typecons;
import std.math;
import std.numeric;
import std.container;
import std.range;
import std.array;
import std.ascii;
// }}}

import std.algorithm, std.array, std.container, std.conv, std.math, std.numeric, std.random, std.range, std.stdio, std.string, std.typecons, core.bitop;

bool check_abc(char[] s, int i)
{
  if (s[i] == 'a') {
    if (i + 2 < s.length && s[i + 1] == 'b' && s[i + 2] == 'c')
      return true;
  } else if (s[i] == 'b') {
    if (i - 1 >= 0 && i + 1 < s.length && s[i - 1] == 'a' && s[i + 1] == 'c')
      return true;
  } else if (s[i] == 'c'){
    if (i - 2 >= 0 && s[i - 1] == 'b' && s[i - 2] == 'a')
      return true;
  }
  return false;
}

void main()
{
    long n, q;
    readf!" %d %d "(n, q);
    char[] s = readln.strip.dup;
    long ans = 0;
    char last = 'c';
    foreach (ch ; s) {
      if (ch == 'a')
        last = 'a';
      else if (ch == 'b' && last == 'a')
        last = 'b';
      else if (ch == 'c' && last == 'b') {
        ans++;
        last = 'c';
      } else
        last = 'c';
    }
    while (q-- > 0) {
      int pos;
      char ch;
      readf!" %d %c "(pos, ch);
      pos--;
      if (check_abc(s, pos))
        ans--;
      s[pos] = ch;
      if (check_abc(s, pos))
        ans++;
      writeln(ans);
    }
}


import core.bitop;
import std.algorithm;
import std.array;
import std.container;
import std.conv;
import std.exception;
import std.functional;
import std.math;
import std.numeric;
import std.range;
import std.stdio;
import std.string;
import std.typecons;

immutable int limit = 10 ^^ 6 + 6;

auto gm = new int [limit];

int g (int n)
{
	if (gm[n] == 0)
	{
		if (n < 10)
		{
			gm[n] = n;
		}
		else
		{
			gm[n] = n.text
			    .map !(q{a - '0'})
			    .filter !(q{a > 0})
			    .fold !(q{a * b}) (1)
			    .g;
		}
	}
	return gm[n];
}

void main ()
{
	auto gm = limit.iota.map !(g).array;
	auto c = new int [limit] [10];
	foreach (d; 1..10)
	{
		foreach (i; 1..limit)
		{
			c[d][i] = c[d][i - 1] + (gm[i] == d);
		}
	}

	int q;
	while (readf (" %s", &q) > 0)
	{
		foreach (r; 0..q)
		{
			int lo, hi, k;
			readf (" %s %s %s", &lo, &hi, &k);
			writeln (c[k][hi] - c[k][lo - 1]);
		}
	}
}

import std.conv, std.functional, std.range, std.stdio, std.string;
import std.algorithm, std.array, std.bigint, std.bitmanip, std.complex, std.container, std.math, std.mathspecial, std.numeric, std.regex, std.typecons;
import core.bitop;

class EOFException : Throwable { this() { super("EOF"); } }
string[] tokens;
string readToken() { for (; tokens.empty; ) { if (stdin.eof) { throw new EOFException; } tokens = readln.split; } auto token = tokens.front; tokens.popFront; return token; }
int readInt() { return readToken.to!int; }
long readLong() { return readToken.to!long; }
real readReal() { return readToken.to!real; }

bool chmin(T)(ref T t, in T f) { if (t > f) { t = f; return true; } else { return false; } }
bool chmax(T)(ref T t, in T f) { if (t < f) { t = f; return true; } else { return false; } }

int binarySearch(alias pred, T)(in T[] as) { int lo = -1, hi = cast(int)(as.length); for (; lo + 1 < hi; ) { const mid = (lo + hi) >> 1; (unaryFun!pred(as[mid]) ? hi : lo) = mid; } return hi; }
int lowerBound(T)(in T[] as, T val) { return as.binarySearch!(a => (a >= val)); }
int upperBound(T)(in T[] as, T val) { return as.binarySearch!(a => (a > val)); }

enum LIM = 10^^6 + 10;

void main() {
  auto fs = new int[LIM];
  fs[0] = 1;
  foreach (n; 1 .. LIM) {
    fs[n] = fs[n / 10] * ((n % 10 == 0) ? 1 : (n % 10));
  }
  auto gs = new int[LIM];
  foreach (n; 1 .. LIM) {
    gs[n] = (n < 10) ? n : gs[fs[n]];
  }

  auto nums = new int[][](10, LIM);
  foreach (k; 0 .. 10) {
    foreach (n; 1 .. LIM) {
      nums[k][n] = nums[k][n - 1] + ((gs[n] == k) ? 1 : 0);
    }
  }

  try {
    for (; ; ) {
      const Q = readInt();
      foreach (q; 0 .. Q) {
        const l = readInt();
        const r = readInt();
        const k = readInt();
        const ans = nums[k][r] - nums[k][l - 1];
        writeln(ans);
      }
    }
  } catch (EOFException e) {
  }
}


import std.stdio, std.array, std.string, std.conv, std.algorithm;
import std.typecons, std.range, std.random, std.math, std.container;
import std.numeric, std.bigint, core.bitop, std.bitmanip, std.regex;

void main() {
    auto s = readln.split.map!(to!int);
    auto W = s[0];
    auto K = s[1];
    auto A = new bool[][](4, W);
    auto C = W/2;

    "YES".writeln;

    outer: foreach (i; 1..3) {
        foreach (j; 1..C) {
            if (K <= 1) break outer;
            A[i][j] = true;
            A[i][W-j-1] = true;
            K -= 2;
        }
    }

    foreach (i; 1..3) {
        if (K == 0) break;
        A[i][C] = true;
        K -= 1;
    }

    foreach (i; 0..4) A[i].map!(a => a ? '#' : '.').writeln;
}

import std.stdio;
import std.range;
import std.array;
import std.string;
import std.conv;
import std.typecons;
import std.algorithm;
import std.container;
import std.typecons;
import std.random;
import std.csv;
import std.regex;
import std.math;
import core.time;
import std.ascii;
import std.digest.sha;
import std.outbuffer;
import std.numeric;

void main()
{
	int n, k;
	readln.chomp.split.tie(n, k);
	if (2 * (n - 2) < k) {
		"NO".writeln;
		return;
	}
	"YES".writeln;
	char[][] ans = new char[][](4, n);
	foreach (i; 0..4) {
		foreach (j; 0..n) {
			ans[i][j] = '.';
		}
	}
	// vertical
	for (int i = 1; i <= 2; ++i) {
		if (k < n - 2) {
			break;
		}
		for (int j = 1; j < n - 1; ++j) {
			ans[i][j] = '#';
		}
		k -= n - 2;
	}
	immutable MID = n / 2;
	if (k % 2 == 1) {
		ans[2][MID] = '#';
		--k;
	}
	for (int i = 1; k > 0; ++i) {
		ans[2][MID - i] = ans[2][MID + i] = '#';
		k -= 2;
	}
	foreach (s; ans) {
		foreach (c; s) {
			c.write;
		}
		writeln;
	}
}

void tie(R, Args...)(R arr, ref Args args)
		if (isRandomAccessRange!R || isArray!R)
in
{
	assert (arr.length == args.length);
}
body
{
	foreach (i, ref v; args) {
		alias T = typeof(v);
		v = arr[i].to!T;
	}
}

void verbose(Args...)(in Args args)
{
	stderr.write("[");
	foreach (i, ref v; args) {
		if (i) stderr.write(", ");
		stderr.write(v);
	}
	stderr.writeln("]");
}

import std.algorithm, std.container, std.conv, std.math, std.range, std.typecons, std.stdio, std.string;

auto rdsp(){return readln.splitter;}
void pick(R,T)(ref R r,ref T t){t=r.front.to!T;r.popFront;}
void readV(T...)(ref T t){auto r=rdsp;foreach(ref v;t)pick(r,v);}

void main()
{
  int n, k; readV(n, k);

  auto b = new bool[][](4, n);

  if (k%2 == 0) {
    foreach (i; 0..k/2)
      b[1][i+1] = b[2][i+1] = true;
  } else if (k <= n-2) {
    foreach (i; 0..k)
      b[1][i+(n-k)/2] = true;
  } else {
    foreach (i; 0..n-2)
      b[1][i+1] = true;
    auto k2 = k-(n-2)+1;
    foreach (i; 0..k2)
      b[2][i+(n-k2)/2] = true;
    b[2][n/2] = false;
  }

  writeln("YES");
  foreach (i; 0..4) {
    foreach (j; 0..n)
      write(b[i][j] ? "#" : ".");
    writeln;
  }
}

import std.stdio;
import std.range;
import std.array;
import std.string;
import std.conv;
import std.typecons;
import std.algorithm;
import std.container;
import std.typecons;
import std.random;
import std.csv;
import std.regex;
import std.math;
import core.time;
import std.ascii;
import std.digest.sha;
import std.outbuffer;
import std.numeric;

void main()
{
	int n, k;
	readln.chomp.split.tie(n, k);
	if (2 * (n - 2) < k) {
		"NO".writeln;
		return;
	}
	char[][] ans = new char[][](4, n);
	foreach (i; 0..4) {
		foreach (j; 0..n) {
			ans[i][j] = '.';
		}
	}
	loop:
	for (int i = 1; i <= 2; ++i) {
		for (int j = 1; j < n - 1; ++j) {
			if (k == 0) {
				break loop;
			}
			ans[i][j] = '#';
			--k;
		}
	}
	"YES".writeln;
	foreach (s; ans) {
		foreach (c; s) {
			writef("%c", c);
		}
		writeln;
	}
}

void tie(R, Args...)(R arr, ref Args args)
		if (isRandomAccessRange!R || isArray!R)
in
{
	assert (arr.length == args.length);
}
body
{
	foreach (i, ref v; args) {
		alias T = typeof(v);
		v = arr[i].to!T;
	}
}

void verbose(Args...)(in Args args)
{
	stderr.write("[");
	foreach (i, ref v; args) {
		if (i) stderr.write(", ");
		stderr.write(v);
	}
	stderr.writeln("]");
}

import std.stdio;
import std.range;
import std.array;
import std.string;
import std.conv;
import std.typecons;
import std.algorithm;
import std.container;
import std.typecons;
import std.random;
import std.csv;
import std.regex;
import std.math;
import core.time;
import std.ascii;
import std.digest.sha;
import std.outbuffer;
import std.numeric;

void main()
{
	int n, k;
	readln.chomp.split.tie(n, k);
	if (2 * (n - 2) < k) {
		"NO".writeln;
		return;
	}
	char[][] ans = new char[][](4, n);
	foreach (i; 0..4) {
		foreach (j; 0..n) {
			ans[i][j] = '.';
		}
	}
	// vertical
	for (int i = 1; i <= 2; ++i) {
		if (k < n - 2) {
			break;
		}
		for (int j = 1; j < n - 1; ++j) {
			ans[i][j] = '#';
		}
		k -= n - 2;
	}
	immutable MID = n / 2;
	if (k % 2 == 1) {
		ans[2][MID] = '#';
		--k;
	}
	for (int i = 1; k > 0; ++i) {
		ans[2][MID - i] = ans[2][MID + i] = '#';
		k -= 2;
	}
	foreach (s; ans) {
		foreach (c; s) {
			c.write;
		}
		writeln;
	}
}

void tie(R, Args...)(R arr, ref Args args)
		if (isRandomAccessRange!R || isArray!R)
in
{
	assert (arr.length == args.length);
}
body
{
	foreach (i, ref v; args) {
		alias T = typeof(v);
		v = arr[i].to!T;
	}
}

void verbose(Args...)(in Args args)
{
	stderr.write("[");
	foreach (i, ref v; args) {
		if (i) stderr.write(", ");
		stderr.write(v);
	}
	stderr.writeln("]");
}

import std.algorithm, std.container, std.conv, std.math, std.range, std.typecons, std.stdio, std.string;

auto rdsp(){return readln.splitter;}
void pick(R,T)(ref R r,ref T t){t=r.front.to!T;r.popFront;}
void readV(T...)(ref T t){auto r=rdsp;foreach(ref v;t)pick(r,v);}

void main()
{
  int n, k; readV(n, k);

  auto isHotel(int i, int j)
  {
    if (i == 0 || i == 3 || j == 0 || j == n-1) return false;
    auto a = j%2 == 1 ? (j-1)*2+(i-1) : (j-2)*2+(i-1)+(n-1);
    return a < k;
  }

  writeln("YES");
  foreach (i; 0..4) {
    foreach (j; 0..n) {
      write(isHotel(i, j) ? "#" : ".");
    }
    writeln;
  }
}

import std.algorithm, std.container, std.conv, std.math, std.range, std.typecons, std.stdio, std.string;

auto rdsp(){return readln.splitter;}
void pick(R,T)(ref R r,ref T t){t=r.front.to!T;r.popFront;}
void readV(T...)(ref T t){auto r=rdsp;foreach(ref v;t)pick(r,v);}

void main()
{
  int n, k; readV(n, k);

  auto isHotel(int i, int j)
  {
    if (i == 0 || i == 3 || j == 0 || j == n-1) return false;
    auto a = j%2 == 1 ? (j-1)+(i-1) : (j-2)+(i-1)+(n-1);
    return a < k;
  }

  writeln("YES");
  foreach (i; 0..4) {
    foreach (j; 0..n) {
      write(isHotel(i, j) ? "#" : ".");
    }
    writeln;
  }
}


import std.algorithm;
import std.stdio;

void main ()
{
	int n, k;
	while (readf (" %s %s", &n, &k) > 0)
	{
		auto a = new int [] [n];
		auto b = new bool [n];
		b[] = false;
		foreach (i; 0..k * 2)
		{
			int v;
			readf (" %s", &v);
			v--;
			b[v] = true;
		}
		foreach (i; 0..n - 1)
		{
			int u, v;
			readf (" %s %s", &u, &v);
			u--;
			v--;
			a[u] ~= v;
			a[v] ~= u;
		}

		long res = 0;

		int recur (int v, int p)
		{
			int num = 0;
			num += b[v];
			foreach (u; a[v])
			{
				if (u != p)
				{
					int t = recur (u, v);
					res += min (t, 2 * k - t);
					num += t;
				}
			}
			return num;
		}

		recur (0, -1);
		writeln (res);
	}
}

import std.stdio;
import std.algorithm;

int N, K;
int[][] G;
int[] d;
long ans = 0;

void dfs(int v, int par) {
	foreach (u; G[v]) {
		if (u == par) continue;
		dfs(u, v); d[v] += d[u];
	}
	ans += min(d[v], 2 * K - d[v]);
}

void main() {
	readf("%d %d", &N, &K);
	G = new int[][N + 1];
	d = new int[N + 1];
	foreach (i; 0..2*K) {
		int In; readf(" %d", &In); d[In] = 1;
	}
	foreach (i; 1..N) {
		int u, v; readf(" %d %d", &u, &v);
		G[u] ~= v; G[v] ~= u;
	}
	dfs(1, 0);
	writeln(ans);
}


import core.bitop;
import std.algorithm;
import std.array;
import std.bitmanip;
import std.container;
import std.conv;
import std.datetime;
import std.functional;
import std.math;
import std.numeric;
import std.range;
import std.stdio;
import std.string;
import std.typecons;
import std.range.interfaces;

Tuple!(int, int)[] solve(int n, int p) {
    Tuple!(int, int)[] ans;
    foreach (i; 0 .. n) {
        ans ~= tuple(i, (i+1) % n);
    }
    foreach (i; 0 .. n) {
        ans ~= tuple(i, (i+2) % n);
    }
    int v = 0, d = 3;
    foreach (_; 0 .. p) {
        ans ~= tuple(v, (v+d) % n);
        v = (v+1) % n;
        if (v == 0) ++d;
    }

    foreach (ref rw; ans) rw[0] += 1, rw[1] += 1;
    return ans;
}

void main()
{
    int t;
    readf("%s", &t);
    readln;

    while (t--) {
        int n, p;
        readf("%s %s", &n, &p);
        readln;

        auto ans = solve(n, p);
        ans.each!(t => writeln(t[0], ' ', t[1]));
    }
}

import core.bitop;
import std.algorithm;
import std.array;
import std.bitmanip;
import std.container;
import std.conv;
import std.datetime;
import std.functional;
import std.math;
import std.numeric;
import std.range;
import std.stdio;
import std.string;
import std.typecons;
import std.range.interfaces;

void solve(int n, int p) {
    Tuple!(int, int)[] ans;
    foreach (i; 0 .. n) {
        ans ~= tuple(i, (i+1) % n);
    }
    foreach (i; 0 .. n) {
        ans ~= tuple(i, (i+2) % n);
    }
    int v = 0, d = 3;
    foreach (_; 0 .. p) {
        ans ~= tuple(v, (v+d) % n);
        v = (v+1) % n;
        if (v == 0) ++d;
    }

    ans.each!(t => writeln(t[0]+1, ' ', t[1]+1));
}

void main()
{
    int t;
    readf("%s", &t);
    readln;

    while (t--) {
        int n, p;
        readf("%s %s", &n, &p);
        readln;

        solve(n, p);
    }
}

import std.algorithm;
import std.array;
import std.container;
import std.conv;
import std.exception;
import std.functional;
import std.math;
import std.numeric;
import std.range;
import std.stdio;
import std.string;
import std.typecons;
import core.bitop;

void main ()
{
	int tests;
	readf (" %s", &tests);
	foreach (test; 0..tests)
	{
		int n, p;
		readf (" %s %s", &n, &p);
		auto a = new bool [] [] (n, n);
		foreach (i; 0..n)
		{
			int j = (i + 1) % n;
			a[i][j] = a[j][i] = true;
			int k = (j + 1) % n;
			a[i][k] = a[k][i] = true;
		}
		int m = 0;
		foreach (i; 0..n)
		{
			foreach (j; i + 1..n)
			{
				if (m < p && !a[i][j])
				{
					m++;
					a[i][j] = a[j][i] = true;
				}
			}
		}
		foreach (i; 0..n)
		{
			foreach (j; i + 1..n)
			{
				if (a[i][j])
				{
					writefln ("%s %s", i + 1, j + 1);
				}
			}
		}
	}
}

import core.bitop;
import std.algorithm;
import std.array;
import std.bitmanip;
import std.container;
import std.conv;
import std.datetime;
import std.functional;
import std.math;
import std.numeric;
import std.range;
import std.stdio;
import std.string;
import std.typecons;
import std.range.interfaces;

void solve(int n, int p) {
    Tuple!(int, int)[] ans;
    foreach (i; 0 .. n) {
        ans ~= tuple(i, (i+1) % n);
    }
    foreach (i; 0 .. n) {
        ans ~= tuple(i, (i+2) % n);
    }
    int v = 1, d = 3;
    foreach (_; 0 .. p) {
        ans ~= tuple(v, (v+d) % n);
        v = (v+1) % n;
        if (v == 0) ++d;
    }

    ans.each!(t => writeln(t[0]+1, ' ', t[1]+1));
}

void main()
{
    int t;
    readf("%s", &t);
    readln;

    while (t--) {
        int n, p;
        readf("%s %s", &n, &p);
        readln;

        solve(n, p);
    }
}


import std.algorithm;
import std.array;
import std.container;
import std.conv;
import std.exception;
import std.functional;
import std.math;
import std.numeric;
import std.range;
import std.stdio;
import std.string;
import std.typecons;
import core.bitop;

string solve (int k, int x, int n, int m)
{
	string [2] res;
	bool found = false;

	alias Tuple !(bool, "b", bool, "e", long, "num") part;
	auto cur = new part [k];
	int [2] d = [n, m];

	string build (int p)
	{
		auto c = cur[p];
		string res = "";
		if (c.b)
		{
			res ~= 'C';
		}
		foreach (i; 0..c.num)
		{
			res ~= "AC";
		}
		foreach (i; c.b + c.e + c.num * 2..d[p])
		{
			res ~= 'B';
		}
		if (c.e)
		{
			res ~= 'A';
		}
		return res;
	}

	void gen (int p)
	{
		if (p == 2)
		{
			foreach (i; 2..k)
			{
				cur[i] = part (cur[i - 2].b,
				               cur[i - 1].e,
				               cur[i - 2].num +
				               cur[i - 1].num +
				               (cur[i - 2].e &&
				                cur[i - 1].b));
			}
			if (cur[k - 1].num == x && !found)
			{
				foreach (i; 0..2)
				{
					res[i] = build (i);
				}
			}
		}
		else
		{
			foreach (b; 0..2)
			{
				foreach (e; 0..2)
				{
					int num = 0;
					while (b + e + num * 2 <= d[p])
					{
						cur[p] = part (cast (bool) b,
						               cast (bool) e,
						               num);
						gen (p + 1);
						num++;
					}
				}
			}
		}
	}

	gen (0);

	if (res == ["", ""])
	{
		return "Happy new year!";
	}
	return res[0] ~ '\n' ~ res[1];
}

void main ()
{
	int k, x, n, m;
	while (readf (" %s %s %s %s", &k, &x, &n, &m) > 0)
	{
		writeln (solve (k, x, n, m));
	}
}

import std.stdio;
import std.range;
import std.array;
import std.functional;
import std.algorithm;
import std.conv;
import std.container;
import std.math;
import std.numeric;
import std.string;

struct P {
    char a, b;
    long c;
}

P[] gen(int n) {
    if (n == 1) {
        return [P('A', 'A', 0),
                P('C', 'C', 0),
                P('X', 'X', 0)];
    }
    P[] ret;
    static const s = "ACX";
    foreach (i; 0 .. n / 2 + 1) {
        foreach (x; 0 .. 3) {
            foreach (y; 0 .. 3) {
                int r = n - i * 2;
                if (s[x] != 'X') r--;
                if (s[y] != 'X') r--;
                if (r < 0) continue;
                if (n == 2 && s[x] == 'A' && s[y] == 'C') continue;
                ret ~= P(s[x], s[y], i);
            }
        }
    }
    return ret;
}

P step(P a, P b) {
    P ret;
    ret.c = a.c + b.c;
    ret.a = a.a;
    ret.b = b.b;
    if (a.b == 'A' && b.a == 'C') {
        ret.c++;
    }
    return ret;
}

long stepK(P a, P b, int k) {
    P t;
    foreach (i; 0 .. k) {
        t = step(a, b);
        a = b;
        b = t;
    }
    return t.c;
}

string format(P p, int n) {
    if (n == 1) {
        return p.a.to!string;
    }
    string ret;
    if (p.a != 'X') n--;
    if (p.b != 'X') n--;
    foreach (i; 0 .. p.c) {
        ret ~= "AC";
    }
    foreach (i; ret.length .. n) {
        ret ~= 'X';
    }
    if (p.a != 'X') ret = p.a ~ ret;
    if (p.b != 'X') ret ~= p.b;
    return ret;
}

void main() {
    int k, x, n, m;
    readf("%d %d %d %d\n", &k, &x, &n, &m);
    P[] a, b;
    a = gen(n);
    b = gen(m);
    foreach (i; a) {
        foreach (j; b) {
            if (stepK(i, j, k - 2) == x) {
                writeln(format(i, n));
                writeln(format(j, m));
                return;
            }
        }
    }
    writeln("Happy new year!");
}

import std.stdio;
import std.range;
import std.array;
import std.functional;
import std.algorithm;
import std.conv;
import std.container;
import std.math;
import std.numeric;
import std.string;

struct P {
    char a, b;
    int c;
}

P[] gen(int n) {
    P[] ret;
    static const s = "ACX";
    foreach (i; 0 .. n / 2 + 1) {
        foreach (x; 0 .. 3) {
            foreach (y; 0 .. 3) {
                int r = n - i * 2;
                if (s[x] != 'X') r--;
                if (s[y] != 'X') r--;
                if (r < 0) continue;
                ret ~= P(s[x], s[y], i);
            }
        }
    }
    return ret;
}

P step(P a, P b) {
    P ret;
    ret.c = a.c + b.c;
    ret.a = a.a;
    ret.b = b.b;
    if (a.b == 'A' && b.a == 'C') {
        ret.c++;
    }
    return ret;
}

int stepK(P a, P b, int k) {
    P t;
    foreach (i; 0 .. k) {
        t = step(a, b);
        a = b;
        b = t;
    }
    return t.c;
}

string format(P p, int n) {
    string ret;
    if (p.a != 'X') n--;
    if (p.b != 'X') n--;
    if (p.a != 'X') ret ~= p.a;
    foreach (i; 0 .. p.c) {
        ret ~= "AC";
    }
    foreach (i; ret.length .. n) {
        ret ~= 'X';
    }
    if (p.b != 'X') ret ~= p.b;
    return ret;
}

void main() {
    int k, x, n, m;
    readf("%d %d %d %d\n", &k, &x, &n, &m);
    P[] a, b;
    a = gen(n);
    b = gen(m);
    foreach (i; a) {
        foreach (j; b) {
            if (stepK(i, j, k - 2) == x) {
                writeln(format(i, n));
                writeln(format(j, m));
                return;
            }
        }
    }
    writeln("Happy new year!");
}

import std.stdio;
import std.range;
import std.array;
import std.functional;
import std.algorithm;
import std.conv;
import std.container;
import std.math;
import std.numeric;
import std.string;

struct P {
    char a, b;
    int c;
}

P[] gen(int n) {
    P[] ret;
    static const s = "ACX";
    foreach (i; 0 .. n / 2 + 1) {
        foreach (x; 0 .. 3) {
            foreach (y; 0 .. 3) {
                int r = n - i * 2;
                if (s[x] != 'X') r--;
                if (s[y] != 'X') r--;
                if (r < 0) continue;
                ret ~= P(s[x], s[y], i);
            }
        }
    }
    return ret;
}

P step(P a, P b) {
    P ret;
    ret.c = a.c + b.c;
    ret.a = a.a;
    ret.b = b.b;
    if (a.b == 'A' && b.a == 'C') {
        ret.c++;
    }
    return ret;
}

int stepK(P a, P b, int k) {
    P t;
    foreach (i; 0 .. k) {
        t = step(a, b);
        a = b;
        b = t;
    }
    return t.c;
}

string format(P p, int n) {
    string ret;
    if (p.a != 'X') n--;
    if (p.b != 'X') n--;
    foreach (i; 0 .. p.c) {
        ret ~= "AC";
    }
    foreach (i; ret.length .. n) {
        ret ~= 'X';
    }
    if (p.a != 'X') ret = p.a ~ ret;
    if (p.a != 'X') ret ~= p.b;
    return ret;
}

void main() {
    int k, x, n, m;
    readf("%d %d %d %d\n", &k, &x, &n, &m);
    P[] a, b;
    a = gen(n);
    b = gen(m);
    foreach (i; a) {
        foreach (j; b) {
            if (stepK(i, j, k - 2) == x) {
                writeln(format(i, n));
                writeln(format(j, m));
                return;
            }
        }
    }
    writeln("Happy new year!");
}

import std.stdio;
import std.range;
import std.array;
import std.functional;
import std.algorithm;
import std.conv;
import std.container;
import std.math;
import std.numeric;
import std.string;

struct P {
    char a, b;
    int c;
}

P[] gen(int n) {
    P[] ret;
    static const s = "ACX";
    foreach (i; 0 .. n / 2 + 1) {
        foreach (x; 0 .. 3) {
            foreach (y; 0 .. 3) {
                int r = n - i * 2;
                if (s[x] != 'X') r--;
                if (s[y] != 'X') r--;
                if (r < 0) continue;
                ret ~= P(s[x], s[y], i);
            }
        }
    }
    return ret;
}

P step(P a, P b) {
    P ret;
    ret.c = a.c + b.c;
    ret.a = a.a;
    ret.b = b.b;
    if (a.b == 'A' && b.a == 'C') {
        ret.c++;
    }
    return ret;
}

int stepK(P a, P b, int k) {
    P t;
    foreach (i; 0 .. k) {
        t = step(a, b);
        a = b;
        b = t;
    }
    return t.c;
}

string format(P p, int n) {
    string ret;
    if (p.a != 'X') n--;
    if (p.b != 'X') n--;
    foreach (i; 0 .. p.c) {
        ret ~= "AC";
    }
    foreach (i; ret.length .. n) {
        ret ~= 'X';
    }
    if (p.a != 'X') ret = p.a ~ ret;
    if (p.b != 'X') ret ~= p.b;
    return ret;
}

void main() {
    int k, x, n, m;
    readf("%d %d %d %d\n", &k, &x, &n, &m);
    P[] a, b;
    a = gen(n);
    b = gen(m);
    foreach (i; a) {
        foreach (j; b) {
            if (stepK(i, j, k - 2) == x) {
                writeln(format(i, n));
                writeln(format(j, m));
                return;
            }
        }
    }
    writeln("Happy new year!");
}

import std.stdio;
import std.range;
import std.array;
import std.functional;
import std.algorithm;
import std.conv;
import std.container;
import std.math;
import std.numeric;
import std.string;

struct P {
    char a, b;
    long c;
}

P[] gen(int n) {
    P[] ret;
    static const s = "ACX";
    foreach (i; 0 .. n / 2 + 1) {
        foreach (x; 0 .. 3) {
            foreach (y; 0 .. 3) {
                int r = n - i * 2;
                if (s[x] != 'X') r--;
                if (s[y] != 'X') r--;
                if (r < 0) continue;
                ret ~= P(s[x], s[y], i);
            }
        }
    }
    return ret;
}

P step(P a, P b) {
    P ret;
    ret.c = a.c + b.c;
    ret.a = a.a;
    ret.b = b.b;
    if (a.b == 'A' && b.a == 'C') {
        ret.c++;
    }
    return ret;
}

long stepK(P a, P b, int k) {
    P t;
    foreach (i; 0 .. k) {
        t = step(a, b);
        a = b;
        b = t;
    }
    return t.c;
}

string format(P p, int n) {
    string ret;
    if (p.a != 'X') n--;
    if (p.b != 'X') n--;
    foreach (i; 0 .. p.c) {
        ret ~= "AC";
    }
    foreach (i; ret.length .. n) {
        ret ~= 'X';
    }
    if (p.a != 'X') ret = p.a ~ ret;
    if (p.b != 'X') ret ~= p.b;
    return ret;
}

void main() {
    int k, x, n, m;
    readf("%d %d %d %d\n", &k, &x, &n, &m);
    P[] a, b;
    a = gen(n);
    b = gen(m);
    foreach (i; a) {
        foreach (j; b) {
            if (stepK(i, j, k - 2) == x) {
                writeln(format(i, n));
                writeln(format(j, m));
                return;
            }
        }
    }
    writeln("Happy new year!");
}

import std.stdio;
import std.range;
import std.array;
import std.functional;
import std.algorithm;
import std.conv;
import std.container;
import std.math;
import std.numeric;
import std.string;

struct P {
    char a, b;
    long c;
}

P[] gen(int n) {
    if (n == 1) {
        return [P('A', 'A', 0),
                P('C', 'C', 0),
                P('X', 'X', 0)];
    }
    P[] ret;
    static const s = "ACX";
    foreach (i; 0 .. n / 2 + 1) {
        foreach (x; 0 .. 3) {
            foreach (y; 0 .. 3) {
                int r = n - i * 2;
                if (s[x] != 'X') r--;
                if (s[y] != 'X') r--;
                if (r < 0) continue;
                ret ~= P(s[x], s[y], i);
            }
        }
    }
    return ret;
}

P step(P a, P b) {
    P ret;
    ret.c = a.c + b.c;
    ret.a = a.a;
    ret.b = b.b;
    if (a.b == 'A' && b.a == 'C') {
        ret.c++;
    }
    return ret;
}

long stepK(P a, P b, int k) {
    P t;
    foreach (i; 0 .. k) {
        t = step(a, b);
        a = b;
        b = t;
    }
    return t.c;
}

string format(P p, int n) {
    if (n == 1) {
        return p.a.to!string;
    }
    string ret;
    if (p.a != 'X') n--;
    if (p.b != 'X') n--;
    foreach (i; 0 .. p.c) {
        ret ~= "AC";
    }
    foreach (i; ret.length .. n) {
        ret ~= 'X';
    }
    if (p.a != 'X') ret = p.a ~ ret;
    if (p.b != 'X') ret ~= p.b;
    return ret;
}

void main() {
    int k, x, n, m;
    readf("%d %d %d %d\n", &k, &x, &n, &m);
    P[] a, b;
    a = gen(n);
    b = gen(m);
    foreach (i; a) {
        foreach (j; b) {
            if (stepK(i, j, k - 2) == x) {
                writeln(format(i, n));
                writeln(format(j, m));
                return;
            }
        }
    }
    writeln("Happy new year!");
}

import std.stdio;
import std.range;
import std.array;
import std.functional;
import std.algorithm;
import std.conv;
import std.container;
import std.math;
import std.numeric;
import std.string;

struct P {
    char a, b;
    int c;
}

P[] gen(int n) {
    P[] ret;
    static const s = "ACX";
    foreach (i; 0 .. n / 2 + 1) {
        foreach (x; 0 .. 3) {
            foreach (y; 0 .. 3) {
                int r = n - i * 2;
                if (s[x] != 'X') r--;
                if (s[y] != 'X') r--;
                if (r < 0) continue;
                ret ~= P(s[x], s[y], i);
            }
        }
    }
    return ret;
}

P step(P a, P b) {
    P ret;
    ret.c = a.c + b.c;
    ret.a = a.a;
    ret.b = b.b;
    if (a.b == 'A' && b.a == 'C') {
        ret.c++;
    }
    return ret;
}

int stepK(P a, P b, int k) {
    P t;
    foreach (i; 0 .. k) {
        t = step(a, b);
        a = b;
        b = t;
    }
    return t.c;
}

string format(P p, int n) {
    string ret;
    if (p.a != 'X') n--;
    if (p.b != 'X') n--;
    if (p.a != 'X') ret ~= p.a;
    foreach (i; 0 .. n / 2) {
        ret ~= "AC";
    }
    foreach (i; ret.length .. n) {
        ret ~= 'X';
    }
    if (p.b != 'X') ret ~= p.b;
    return ret;
}

void main() {
    int k, x, n, m;
    readf("%d %d %d %d\n", &k, &x, &n, &m);
    P[] a, b;
    a = gen(n);
    b = gen(m);
    foreach (i; a) {
        foreach (j; b) {
            if (stepK(i, j, k - 2) == x) {
                writeln(format(i, n));
                writeln(format(j, m));
                return;
            }
        }
    }
    writeln("Happy new year!");
}


import std.stdio, std.conv, std.functional, std.string;
import std.algorithm, std.array, std.container, std.range, std.typecons;
import std.bigint, std.numeric, std.math, std.random;
import core.bitop;

string FMT_F = "%.10f";

static File _f;
void file_io(string fn) { _f = File(fn, "r"); }
static string[] s_rd;
T _RD(T = long)() { while(!s_rd.length) s_rd = readln.chomp.split; string res = s_rd[0]; s_rd.popFront; return res.to!T; }
T _RD(T = long)(File f) { while(!s_rd.length) s_rd = f.readln.chomp.split; string res = s_rd[0]; s_rd.popFront; return res.to!T; }
T[] _RDA(T = long)(T fix = 0) { auto r = readln.chomp.split.to!(T[]); r[] += fix; return r; }
T[] _RDA(T = long)(File f, T fix = 0) { auto r = f.readln.chomp.split.to!(T[]); r[] += fix; return r; }
T RD(T = long)() { if (_f.isOpen) return _RD!T(_f); else return _RD!T; }
T[] RDA(T = long)(T fix = 0) { if (_f.isOpen)  return _RDA!T(_f, fix); else return _RDA!T(fix); }

size_t[] MAKE_IDX(alias less = "a < b", Range)(Range range) { auto idx = new size_t[](range.length); makeIndex!(less)(range, idx); return idx;}
size_t MIN_POS(alias less = "a < b", Range)(Range range) { auto r = minPos!(less)(range); return range.length - r.length; }

void chmin(T)(ref T x, T y) { x = min(x, y); } void chmax(T)(ref T x, T y) { x = max(x, y); }
bool inside(T)(T x, T b, T e) { return x >= b && x < e; }
T lcm(T)(T x, T y) { return x * (y / gcd(x, y)); }
double[] rotate(double[] vec, double rad) { return [cos(rad)*vec[0] - sin(rad)*vec[1], sin(rad)*vec[0] + cos(rad)*vec[1]]; }

//long mod = 10^^9 + 7;
long mod = 998_244_353;
//long mod = 1_000_003;
void moda(ref long x, long y) { x = (x + y) % mod; }
void mods(ref long x, long y) { x = ((x + mod) - (y % mod)) % mod; }
void modm(ref long x, long y) { x = (x * y) % mod; }
void modpow(ref long x, long y) { if (!y) { x = 1; return; } auto t = x; x.modpow(y>>1); x.modm(x); if (y&1) x.modm(t); }
void modd(ref long x, long y) { y.modpow(mod - 2); x.modm(y); }

void main()
{
	auto t = RD!int;
	auto ans = new bool[](t);
	foreach (ti; 0..t)
	{
		auto n = RD;
		auto m = RD;
		auto k = RD-1;

		if (m < n-1) continue;
		auto cnt = n * (n-1) / 2;
		if (m > cnt) continue;
		long kk;
		if (n == 1)
			kk = 0;
		else if (m == cnt)
			kk = 1;
		else
			kk = 2;
		debug writeln("kk:", kk);
		if (kk < k)
			ans[ti] = true;
	}

	foreach (e; ans)
		writeln(e ? "YES" : "NO");
	stdout.flush;
	debug readln;
}

import std.algorithm, std.array, std.container, std.conv, std.format, std.functional, std.math, std.numeric, std.random, std.range, std.stdio, std.string, std.typecons, core.bitop;

void main()
{
  long t;
  readf(" %d ", &t);
  while (t--) {
    long n, m, k;
    readf(" %d %d %d ", &n, &m, &k);
    if (m < n - 1) {
      writeln("NO");
      continue;
    }
    if (m > n * (n - 1) / 2) {
      writeln("NO");
      continue;
    }
    long min_d = 2;
    if (m == n * (n - 1) / 2) {
      min_d = 1;
    }
    if (n == 1) {
      min_d = 0;
    }
    writeln(min_d < k - 1 ? "YES" : "NO");
  }
}

import std.stdio, std.conv, std.functional, std.string;
import std.algorithm, std.array, std.container, std.range, std.typecons;
import std.bigint, std.numeric, std.math, std.random;
import core.bitop;

string FMT_F = "%.10f";

static File _f;
void file_io(string fn) { _f = File(fn, "r"); }
static string[] s_rd;
T _RD(T = long)() { while(!s_rd.length) s_rd = readln.chomp.split; string res = s_rd[0]; s_rd.popFront; return res.to!T; }
T _RD(T = long)(File f) { while(!s_rd.length) s_rd = f.readln.chomp.split; string res = s_rd[0]; s_rd.popFront; return res.to!T; }
T[] _RDA(T = long)(T fix = 0) { auto r = readln.chomp.split.to!(T[]); r[] += fix; return r; }
T[] _RDA(T = long)(File f, T fix = 0) { auto r = f.readln.chomp.split.to!(T[]); r[] += fix; return r; }
T RD(T = long)() { if (_f.isOpen) return _RD!T(_f); else return _RD!T; }
T[] RDA(T = long)(T fix = 0) { if (_f.isOpen)  return _RDA!T(_f, fix); else return _RDA!T(fix); }

size_t[] MAKE_IDX(alias less = "a < b", Range)(Range range) { auto idx = new size_t[](range.length); makeIndex!(less)(range, idx); return idx;}
size_t MIN_POS(alias less = "a < b", Range)(Range range) { auto r = minPos!(less)(range); return range.length - r.length; }

void chmin(T)(ref T x, T y) { x = min(x, y); } void chmax(T)(ref T x, T y) { x = max(x, y); }
bool inside(T)(T x, T b, T e) { return x >= b && x < e; }
T lcm(T)(T x, T y) { return x * (y / gcd(x, y)); }
double[] rotate(double[] vec, double rad) { return [cos(rad)*vec[0] - sin(rad)*vec[1], sin(rad)*vec[0] + cos(rad)*vec[1]]; }

//long mod = 10^^9 + 7;
long mod = 998_244_353;
//long mod = 1_000_003;
void moda(ref long x, long y) { x = (x + y) % mod; }
void mods(ref long x, long y) { x = ((x + mod) - (y % mod)) % mod; }
void modm(ref long x, long y) { x = (x * y) % mod; }
void modpow(ref long x, long y) { if (!y) { x = 1; return; } auto t = x; x.modpow(y>>1); x.modm(x); if (y&1) x.modm(t); }
void modd(ref long x, long y) { y.modpow(mod - 2); x.modm(y); }

void main()
{
	auto t = RD!int;
	auto ans = new bool[](t);
	foreach (ti; 0..t)
	{
		auto n = RD!int;
		auto m = RD!int;
		auto k = RD!int-1;

		if (m < n-1) continue;
		auto cnt = n * (n-1) / 2;
		if (m > cnt) continue;
		long kk;
		if (n == 1)
			kk = 0;
		else if (m == cnt)
			kk = 1;
		else
			kk = 2;
		debug writeln("kk:", kk);
		if (kk < k)
			ans[ti] = true;
	}

	foreach (e; ans)
		writeln(e ? "YES" : "NO");
	stdout.flush;
	debug readln;
}


import std.algorithm;
import std.conv;
import std.range;
import std.stdio;
import std.string;
import std.typecons;

void main ()
{
	int tests;
	readf !(" %s") (tests);
	foreach (test; 0..tests)
	{
		int n, a, b;
		readf !(" %s %s %s") (n, a, b);
		string s;
		s.reserve (n);
		foreach (i; 0..n)
		{
			s ~= cast (char) (i % b + 'a');
		}
		writeln (s);
	}
}

import std.stdio, std.algorithm, std.conv, std.array, std.string, std.math, std.typecons, std.numeric;

void main()
{
    auto T = readln.chomp.to!int;
    foreach (_; 0..T) {
        auto nab = readln.split.to!(int[]);
        auto N = nab[0];
        auto A = nab[1];
        auto B = nab[2];

        char[] rs, ss;
        foreach (i; 0..A) {
            rs ~= (min(i, B-1) + 'a').to!char;
        }
        foreach (i; 0..N) {
            ss ~= rs[i%A];
        }
        writeln(ss);
    }
}

import std.stdio, std.conv, std.functional, std.string;
import std.algorithm, std.array, std.container, std.range, std.typecons;
import std.bigint, std.numeric, std.math, std.random;
import core.bitop;

string FMT_F = "%.10f";

static File _f;
void file_io(string fn) { _f = File(fn, "r"); }
static string[] s_rd;
T _RD(T = long)() { while(!s_rd.length) s_rd = readln.chomp.split; string res = s_rd[0]; s_rd.popFront; return res.to!T; }
T _RD(T = long)(File f) { while(!s_rd.length) s_rd = f.readln.chomp.split; string res = s_rd[0]; s_rd.popFront; return res.to!T; }
T[] _RDA(T = long)(T fix = 0) { auto r = readln.chomp.split.to!(T[]); r[] += fix; return r; }
T[] _RDA(T = long)(File f, T fix = 0) { auto r = f.readln.chomp.split.to!(T[]); r[] += fix; return r; }
T RD(T = long)() { if (_f.isOpen) return _RD!T(_f); else return _RD!T; }
T[] RDA(T = long)(T fix = 0) { if (_f.isOpen)  return _RDA!T(_f, fix); else return _RDA!T(fix); }

size_t[] MAKE_IDX(alias less = "a < b", Range)(Range range) { auto idx = new size_t[](range.length); makeIndex!(less)(range, idx); return idx;}
size_t MIN_POS(alias less = "a < b", Range)(Range range) { auto r = minPos!(less)(range); return range.length - r.length; }

void chmin(T)(ref T x, T y) { x = min(x, y); } void chmax(T)(ref T x, T y) { x = max(x, y); }
bool inside(T)(T x, T b, T e) { return x >= b && x < e; }
T lcm(T)(T x, T y) { return x * (y / gcd(x, y)); }

long mod = 10^^9 + 7;
//long mod = 998_244_353;
//long mod = 1_000_003;
void moda(T)(ref T x, T y) { x = (x + y) % mod; }
void mods(T)(ref T x, T y) { x = ((x + mod) - (y % mod)) % mod; }
void modm(T)(ref T x, T y) { x = (x * y) % mod; }
void modpow(T)(ref T x, T y) { if (!y) { x = 1; return; } auto t = x; x.modpow(y>>1); x.modm(x); if (y&1) x.modm(t); }
void modd(T)(ref T x, T y) { x.modm(y.modpow(mod - 2)); }

void main()
{
	auto t = RD!int;
	auto ans = new string[](t);
	foreach (ti; 0..t)
	{
		auto n = RD!int;
		auto a = RD!int;
		auto b = RD!int;

		auto loop = a - b;
		int num;
		int cnt;
		while (ans[ti].length < n)
		{
			if (cnt % a < loop)
			{
				ans[ti] ~= 'a';
			}
			else
			{
				ans[ti] ~= cast(char)('a'+(num%b));
				++num;
			}
			++cnt;
		}
	}

	foreach (e; ans)
		writeln(e);
	stdout.flush;
	debug readln;
}