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 long[](t);
	foreach (ti; 0..t)
	{
		auto n = RD!int;
		auto m = RD!int;
		auto a = RD!int-1;
		auto b = RD!int-1;
		auto c = RD!int-1;
		auto p = RDA;

		auto edges = new int[][](n);
		foreach (i; 0..m)
		{
			auto u = RD!int-1;
			auto v = RD!int-1;
			edges[u] ~= v;
			edges[v] ~= u;
		}

		long[] search(int s)
		{
			int[] open = [s];
			auto dist = new long[](n);
			dist[] = long.max;
			dist[s] = 0;
			while (!open.empty)
			{
				auto from = open.front; open.popFront;
				auto d = dist[from]+1;
				foreach (to; edges[from])
				{
					if (d < dist[to])
					{
						open ~= to;
						dist[to] = d;
					}
				}
			}
			return dist;
		}
		auto dist_a = search(a);
		auto dist_b = search(b);
		auto dist_c = search(c);

		p.sort();
		auto pp = new long[](p.length+1);
		foreach (i; 0..p.length)
		{
			pp[i+1] = pp[i] + p[i];
		}

		ans[ti] = long.max;
		foreach (i; 0..n)
		{
			if (dist_b[i]+dist_a[i]+dist_c[i] > p.length) continue;
			auto c1 = pp[cast(int)dist_b[i]];
			auto c2 = pp[cast(int)(dist_b[i]+dist_a[i])] - c1;
			auto c3 = pp[cast(int)(dist_b[i]+dist_a[i]+dist_c[i])] - (c1+c2);
			ans[ti].chmin(c1*2+c2+c3);
		}
	}

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

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

void main ()
{
	readln;
	int n, m, a, b, c;
	while (readf !(" %s %s %s %s %s") (n, m, a, b, c) > 0)
	{
		a -= 1;
		b -= 1;
		c -= 1;
		readln;

		auto p = readln.splitter.map !(to !(int)).array;
		sort (p);
		auto s = [0L] ~ cumulativeFold !(q{a + b}) (p, 0L).array;

		auto adj = new int [] [n];
		foreach (j; 0..m)
		{
			int u, v;
			readf !(" %s %s") (u, v);
			u -= 1;
			v -= 1;
			adj[u] ~= v;
			adj[v] ~= u;
		}

		int [] bfs (int start)
		{
			auto d = new int [n];
			d[] = int.max;
			d[start] = 0;
			int [] q;
			q ~= start;
			foreach (i; 0..n)
			{
				auto v = q.front;
				q.popFront ();
				q.assumeSafeAppend ();
				foreach (u; adj[v])
				{
					if (d[u] == int.max)
					{
						d[u] = d[v] + 1;
						q ~= u;
					}
				}
			}
			return d;
		}

		auto da = bfs (a);
		auto db = bfs (b);
		auto dc = bfs (c);

		long res = long.max;
		foreach (u; 0..n)
		{
			auto common = db[u];
			auto total = da[u] + db[u] + dc[u];
			debug {writeln (u + 1, ": ", common, ", ", total);}
			if (total <= m)
			{
				res = min (res, s[common] + s[total]);
			}
		}
		writeln (res);
	}
}


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 char[][](T);
	foreach (ti; 0..T)
	{
		auto n = RD!int;
		auto s = RD!string;

		ans[ti].length = n;

		int pos;
		foreach (i; 0..n)
		{
			if (s[i] == '?') continue;
			pos = i;
			break;
		}
		foreach (i; pos..n)
		{
			if (s[i] != '?')
				ans[ti][i] = s[i];
			else if (i == 0)
			{
				ans[ti][i] = 'R';
			}
			else
			{
				if (ans[ti][i-1] == 'R')
					ans[ti][i] = 'B';
				else
					ans[ti][i] = 'R';
			}
		}
		foreach_reverse (i; 0..pos)
		{
			if (s[i] != '?')
				ans[ti][i] = s[i];
			else
			{
				if (ans[ti][i+1] == 'R')
					ans[ti][i] = 'B';
				else
					ans[ti][i] = 'R';
			}
		}
	}

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

immutable multi = true;

void solve(int tc)
{
	auto n = readInt!int;
	auto s = readString;
	int prev = -1;
	char[] ans = new char[](n);
	foreach(i; 0 .. n)
	{
		if (s[i] != '?')
		{
			foreach_reverse(j; prev+1 .. i+1)
			{
				if (j%2 == i%2)
					ans[j] = s[i];
				else
					ans[j] = s[i] == 'R'? 'B' : 'R';
			}
			prev = i;
		}
		else
		{
		}
	}
	foreach(j; prev+1 .. n)
	{
		if ((prev+2)%2 == j%2)
		{
			ans[j] = prev == -1? 'R' : s[prev];
		}
		else
		{
			ans[j] = prev == -1? 'B' : (s[prev] == 'R'? 'B' : 'R');
		}
	}
	ans.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;
}
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;
// }}}

immutable multi = true;

void solve(int tc)
{
	auto n = readInt!int;
	auto s = readString;
	int prev = -1;
	char[] ans = new char[](n);
	foreach(i; 0 .. n)
	{
		if (s[i] != '?')
		{
			foreach_reverse(j; prev+1 .. i+1)
			{
				if (j%2 == i%2)
					ans[j] = s[i];
				else
					ans[j] = s[i] == 'R'? 'B' : 'R';
			}
			prev = i;
		}
		else
		{
		}
	}
	foreach(j; prev+1 .. n)
	{
		if (prev%2 == j%2)
		{
			ans[j] = prev == -1? 'R' : s[prev];
		}
		else
		{
			ans[j] = prev == -1? 'B' : (s[prev] == 'R'? 'B' : 'R');
		}
	}
	ans.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;
}
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;
import std.conv;
import std.range;
import std.stdio;
import std.string;

immutable int mod  = 1_000_000_007;
immutable int base =            10;

void main ()
{
	string s;
	while ((s = readln.strip) != "")
	{
		auto n = s.length.to !(int);
		long res = 0;
		long cur = 1;
		long add = 0;
		foreach (k; 0..n)
		{
			auto mult = ((n - k) * (n - k - 1L) / 2) % mod;
			mult = (mult * cur + add) % mod;
			res = (res + mult * (s[n - k - 1] - '0')) % mod;
			add = (add + cur * (k + 1L)) % mod;
			cur = (cur * base) % mod;
		}
		writeln (res);
	}
}

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;

long pmod(long a, long m)
{
  if (a < 0) return (a % m) + m;
  return a % m;
}

void main(string[] args)
{
  enum p = 1_000_000_000 + 7;
  auto n = next!string;
  auto tenpow = new long[](n.length);
  tenpow[n.length - 1] = 1;
  foreach_reverse(i; 0 .. n.length - 1)
    tenpow[i] = (tenpow[i + 1] * 10) % p;
  long rightNum = 0;
  foreach(d; n) rightNum = ((rightNum * 10) % p + long(d - '0')) % p;
  long leftSum = 0;
  long leftNum = 0;
  long res = 0;
  foreach(i; 0 .. n.length)
    {
      long li = cast(long)i;
      long dig = n[i] - '0';
      rightNum = pmod(rightNum - (dig * tenpow[i]) % p, p);

      res = (res%p + (rightNum * (li + 1))%p + (leftSum * tenpow[i])%p)%p;

      leftNum = ((leftNum * 10) % p + dig)%p;
      leftSum = (leftSum + leftNum) % p;
    }
  res.writeln;
}

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, 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) { y.modpow(mod - 2); x.modm(y); }

void main()
{
	auto n = RD!string;

	auto pat = new long[](n.length+1);
	foreach (i; 0..n.length)
	{
		pat[i+1] = pat[i];
		long tmp = 10;
		tmp.modpow(i);
		tmp.modm(i+1);
		pat[i+1].moda(tmp);
	}

	long ans;
	foreach (i; 0..n.length)
	{
		{
			long num = n[i]-'0';
			long left = i;
			left *= (i+1);
			left /= 2;
			left %= mod;
			long digit = 10;
			digit.modpow(n.length-i-1);
			num.modm(digit);
			left.modm(num);
			ans.moda(left);
			debug writeln("i:", i, " ans:", ans);
		}
		{
			long num = n[i]-'0';
			num.modm(pat[n.length-i-1]);
			ans.moda(num);
			debug writeln("i:", i, " ans:", ans);
		}
	}

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

// Cheese-Cracker: cheese-cracker.github.io

const ll PRIME = 10L^^9 + 7;

void play(){
    dchar[] nummer;
    nummer = rd!(dchar[]);
    ll[] arr;
    foreach(c; nummer){
        arr ~= c-'0';
    }
    int n = arr.length.to!int;
    ll res = 0;
    // Ten-> Power of Ten, RevNN -> Reverse Natural Numbers
    ll tim = 0, ten = 1, revnn = 0;
    foreach_reverse(i; 0..n){
        // Add Before
        ll mul = ( ( 1L * i * (i + 1))/2L ) % PRIME;
        mul *= ten;
        mul %= PRIME;
        res += mul*arr[i];
        res %= PRIME;

        // Add After
        res += revnn * arr[i];
        res %= PRIME;

        // Remove Number Value

        show(ten, tim, mul*ten*arr[i], revnn);

        // Update Tim & Ten
        tim *= 10; tim += 1; tim %= PRIME;
        revnn *= 10; revnn += tim; revnn %= PRIME;
        ten *= 10; ten %= PRIME;

    }
    writeln(res);
}

int main(){
    long t = 1;
    /* t = rd;        // Toggle! */
    while(t--) play();  // Let's play!
    stdout.flush;
    return 0;
}

/**********It's A Me Mario!**********/
import std.stdio, std.conv, std.functional, std.string, std.algorithm;
import std.container, std.range, std.typecons, std.numeric, std.math, std.random;
alias ll = long;
alias rbt = RedBlackTree;
alias sr = SortedRange;
alias tup = Tuple!(long, long);
static string[] inp;
T rd(T = long)(){while(!inp.length) inp = readln.chomp.split; string a = inp[0]; inp.popFront; return a.to!T;}
T[] rdarr(T = long)(T fix = 0){ auto r = readln.chomp.split.to!(T[]); r[] += fix; return r; }
void show(A...)(A a) { debug{ foreach(t; a){ write(t, "| "); } writeln; } }

// Cheese-Cracker: cheese-cracker.github.io

const ll PRIME = 10L^^9 + 7;

void play(){
    dchar[] nummer;
    nummer = rd!(dchar[]);
    ll[] arr;
    foreach(c; nummer){
        arr ~= c-'0';
    }
    int n = arr.length.to!int;
    ll res = 0;
    // Ten-> Power of Ten, RevNN -> Reverse Natural Numbers
    ll tim = 0, ten = 1, revnn = 0;
    foreach_reverse(i; 0..n){
        // Add Before
        ll mul = (i*(i+1))/2;
        mul %= PRIME;
        res += (mul*ten % PRIME)*arr[i];
        res %= PRIME;

        // Add After
        res += revnn * arr[i];
        res %= PRIME;

        // Remove Number Value

        show(ten, tim, mul*ten*arr[i], revnn);

        // Update Tim & Ten
        tim *= 10; tim += 1; tim %= PRIME;
        revnn *= 10; revnn += tim; revnn %= PRIME;
        ten *= 10; ten %= PRIME;

    }
    writeln(res);
}

int main(){
    long t = 1;
    /* t = rd;        // Toggle! */
    while(t--) play();  // Let's play!
    stdout.flush;
    return 0;
}

/**********It's A Me Mario!**********/
import std.stdio, std.conv, std.functional, std.string, std.algorithm;
import std.container, std.range, std.typecons, std.numeric, std.math, std.random;
alias ll = long;
alias rbt = RedBlackTree;
alias sr = SortedRange;
alias tup = Tuple!(long, long);
static string[] inp;
T rd(T = long)(){while(!inp.length) inp = readln.chomp.split; string a = inp[0]; inp.popFront; return a.to!T;}
T[] rdarr(T = long)(T fix = 0){ auto r = readln.chomp.split.to!(T[]); r[] += fix; return r; }
void show(A...)(A a) { debug{ foreach(t; a){ write(t, "| "); } writeln; } }

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) { y.modpow(mod - 2); x.modm(y); }

void main()
{
	auto n = RD!string;

	auto pat = new long[](n.length+1);
	foreach (i; 0..n.length)
	{
		pat[i+1] = pat[i];
		long tmp = 10;
		tmp.modpow(i);
		tmp.modm(i+1);
		pat[i+1].moda(tmp);
	}

	long ans;
	foreach (i; 0..n.length)
	{
		{
			long num = n[i]-'0';
			long left = i*(i+1)/2;
			long digit = 10;
			digit.modpow(n.length-i-1);
			num.modm(digit);
			left.modm(num);
			ans.moda(left);
			debug writeln("i:", i, " ans:", ans);
		}
		{
			long num = n[i]-'0';
			num.modm(pat[n.length-i-1]);
			ans.moda(num);
			debug writeln("i:", i, " ans:", ans);
		}
	}

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


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 long[](t);
	foreach (ti; 0..t)
	{
		auto n = RD!int;
		auto k = RD!int;

		long x = n;
		for (long i = 2; i*i <= n; ++i)
		{
			if (n % i == 0)
			{
				x = i;
				break;
			}
		}
		ans[ti] = n + x + 2 * (k-1);
	}

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

import std.stdio;
import std.range;
import std.algorithm;

void main()
{
    auto arr = iota(1100000).array;
    foreach (e, i; arr) {
        if (e != i || i < 2) continue;
        for (int j = i + i; j < arr.length; j += i) {
            arr[j] = min(arr[j], i);
        }
    }

    uint t, n, k;
    scanf("%d", &t);
    while (t--) {
        scanf("%d%d", &n, &k);
        if (k > 0 && n % 2 == 1) {
          k--;
          n += arr[n];
        }
        n += 2 * k;
        writef!"%d\n"(n);
    }
}

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;
    auto ps = new long[](10^^6+1);
    foreach (i; 2..10^^6+1) if (ps[i] == 0) {
        ps[i] = i;
        auto x = i;
        while (x <= 10^^6) {
            if (ps[x] == 0) ps[x] = i;
            x += i;
        }
    }
    foreach (_t; 0..T) {
        auto nk = readln.split.to!(long[]);
        auto N = nk[0];
        auto K = nk[1];
        writeln(N + ps[N.to!size_t] + 2*(K-1));
    }
}

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;
    auto ps = new long[](10^^6+1);
    foreach (i; 2..10^^6+1) if (ps[i] == 0) {
        ps[i] = i;
        auto x = i;
        while (x <= 10^^6) {
            ps[x] = i;
            x += i;
        }
    }
    foreach (_t; 0..T) {
        auto nk = readln.split.to!(long[]);
        auto N = nk[0];
        auto K = nk[1];
        writeln(N + ps[N.to!size_t] + 2*(K-1));
    }
}


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;

void main() {
    auto s = readln.split.map!(to!int);
    auto N = s[0];
    auto K = s[1];
    auto A = readln.split.map!(to!int).array;

    int p;
    int[] primes;
    int[] primes_n;
    foreach (i; 2..10^^5) {
        if (K % i == 0) {
            p += 1;
            primes ~= i;
            primes_n ~= 0;
        }
        while (K % i == 0) {
            K /= i;
            primes_n[p-1] += 1;
        }
    }
    if (K > 1) {
        p += 1;
        primes ~= K;
        primes_n ~= 1;
    }

    auto cumsum = new int[][](N+1, p);
    foreach (i; 0..N) {
        auto k = A[i];
        foreach (j; 0..p) {
            while (k % primes[j] == 0) {
                cumsum[i+1][j] += 1;
                k /= primes[j];
            }
        }
    }

    foreach (i; 0..N) {
        cumsum[i+1][] += cumsum[i][];
    }

    long ans = 0;
    auto cs = new int[](p);

    foreach (i; 0..N) {
        int hi = N;
        int lo = i - 1;
        while (hi - lo > 1) {
            int mid = (hi + lo) / 2;
            cs[] = cumsum[mid + 1][] - cumsum[i][];
            if (p.iota.map!(i => cs[i] >= primes_n[i]).all) hi = mid;
            else lo = mid;
        }
        ans += max(N - lo - 1, 0);
    }

    ans.writeln;
}

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.numeric;
import std.range;

void main(string[] args)
{
  inputFile = stdin;
  debug inputFile = File(args[1]);
  auto n = next!int;
  auto k = next!long;
  auto a = next!long(n);
  foreach(ref ai; a) ai %= k;
  auto st = SegmentTree!(long, (x, y) => (x * y) % k, "mul")(a);
  iota(0, n)
    .map!(i => cast(long)n - firstThat!(j => st.mul(i, j) == 0)(i, n - 1))
    .sum
    .writeln;
}

// BIN SEARCH
auto firstThat(alias pred, T)(T i, T j)
{
  T first = j + 1;
  while(i <= j)
    {
      auto mid = (i + j) / 2;
      if (pred(mid))
	{
	  first = mid;
	  j = mid - 1;
	}
      else
	{
	  i = mid + 1;
	}
    }
  return first;
}

// Segment Tree
struct SegmentTree(T, alias f, string getMethodName = "get")
{
  static assert(is(typeof((){T x, y; return f(x, y);}()) == T));
  class Node
  {
    size_t low, high;
    size_t length() {return high - low + 1;}
    this(size_t l, size_t h)
    {
      low = l;
      high = h;
    }
    T fValue;
    Node firstHalf, secondHalf;
    bool contains(size_t i, size_t j)
    {
      return max(low, i) <= min(high, j);
    }
    bool inside(size_t i, size_t j)
    {
      return i <= low && high <= j;
    }
  }
  Node _root;
  this(T[] arr)
  {
    _root = new Node(0, arr.length - 1);
    void fill(Node node)
    {
      if (node.length == 1) {node.fValue = arr[node.low]; return;}
      size_t mid = (node.low + node.high) / 2;
      node.firstHalf = new Node(node.low, mid);
      fill(node.firstHalf);
      node.secondHalf = new Node(mid + 1, node.high);
      fill(node.secondHalf);
      node.fValue = f(node.firstHalf.fValue, node.secondHalf.fValue);
    }
    fill(_root);
  }
  mixin(q{alias }, getMethodName, q{ = fRange;});
  T fRange(size_t i, size_t j, Node node = null)
  {
    if (node is null) node = _root;
    debug assert(node !is null);
    debug assert(node.contains(i, j), text(node.low, " ", node.high, " ", i, " ", j));
    if (node.inside(i, j)) return node.fValue;

    debug assert((node.firstHalf !is null && node.firstHalf.contains(i, j))
		 || (node.secondHalf !is null && node.secondHalf.contains(i, j)));

    if (node.firstHalf !is null && node.firstHalf.contains(i, j))
      {
	if (node.secondHalf !is null && node.secondHalf.contains(i, j))
	  return f(fRange(i, j, node.firstHalf), fRange(i, j, node.secondHalf));
	return fRange(i, j, node.firstHalf);
      }
    else
      {
	debug assert(node.secondHalf !is null && node.secondHalf.contains(i, j));
	return fRange(i, j, node.secondHalf);
      }
  }
}

// INPUT

enum InputStyle
  {
    byChunk, byLine
  };
enum inputStyle = InputStyle.byLine;

File inputFile;
string popWord();
static if (inputStyle == InputStyle.byChunk)
  {
    const chunkSize = 1024 * 1024 * 8;
    const wordSize = 4096;
    char[chunkSize] chunkBuff;
    char[] currChunk;
    void renewChunk()
    {
      if (inputFile.eof)
        currChunk = null;
      else
        currChunk = inputFile.rawRead(chunkBuff);
    }
    char[wordSize] wordBuff;
    char[] word;
    string popWord()
    {
      if (currChunk.length == 0)
        renewChunk;
      assert(currChunk.length > 0);
      while (currChunk[0].isWhite)
        {

          currChunk = currChunk[1 .. $];
          if (currChunk.length == 0)
            renewChunk;
        }
      word = wordBuff[0 .. 0];
      while (!currChunk[0].isWhite)
        {
          word.length++;
          word[$ - 1] = currChunk[0];
          currChunk = currChunk[1 .. $];
          if (currChunk.length == 0)
            {
              renewChunk;
              if (currChunk.length == 0)
                return cast(string) word;
            }
        }
      return cast(string) word;
    }
  }
 else
   {
     DList!string _words;
     string popWord()
     {
       while (_words.empty)
         {
           foreach(w; inputFile.readln.split)
             {
               _words.insertBack(w);
             }
         }
       auto word = _words.front;
       _words.removeFront;
       return word;
     }
   }
T next(T)()
{
  return to!T(popWord);
}
auto next(T, S...)(S s)
{
  static if (S.length == 0)
    {
      return to!T(popWord);
    }
  else
    {
      auto res = new typeof(next!T(s[1 .. $]))[](cast(size_t)s[0]);
      foreach(ref elem; res)
        elem = next!T(s[1 .. $]);
      return res;
    }
}

// tested by Hightail - https://github.com/dj3500/hightail
import std.stdio, std.string, std.conv, std.algorithm;
import std.range, std.array, std.math, std.typecons, std.container, core.bitop;

int n, k;
int[] a;

void main() {
    scan(n, k);
    a = readln.split.to!(int[]);

    if (k == 1) {
        writeln(1L * n * (n + 1) / 2L);
        return;
    }

    auto p = new int[](0);
    auto q = new int[](0);

    for (int d = 2; d*d <= k; d++) {
        if (k % d == 0) {
            p ~= d;
            int cnt = 0;

            while (k % d == 0) {
                cnt++;
                k /= d;
            }

            q ~= cnt;
        }
    }

    if (k > 1) {
        p ~= k;
        q ~= 1;
    }

    debug {
        writeln("p:", p);
        writeln("q:", q);
    }

    int m = p.length.to!int;

    auto div = new int[][](n, m);

    foreach (i ; 0 .. n) {
        foreach (j ; 0 .. m) {
            while (a[i] % p[j] == 0) {
                div[i][j]++;
                a[i] /= p[j];
            }
        }
    }

    debug {
        writefln("%(%(%s %)\n%)", div);
    }

    auto cnt = new int[](m);
    long ans;

    for (int l, r; r < n + 1; l++) {
        for (; r < n + 1; r++) {
            if (iota(m).all!(i => cnt[i] >= q[i])) {
                ans += n + 1 - r;
                break;
            }
            else {
                if (r == n) {
                    writeln(ans);
                    return;
                }

                cnt[] += div[r][];
            }
        }

        cnt[] -= div[l][];
    }

    writeln(ans);
}

void scan(T...)(ref T args) {
    string[] line = readln.split;
    foreach (ref arg; args) {
        arg = line.front.to!(typeof(arg));
        line.popFront();
    }
    assert(line.empty);
}

void fillAll(R, T)(ref R arr, T value) {
    static if (is(typeof(arr[] = value))) {
        arr[] = value;
    }
    else {
        foreach (ref e; arr) {
            fillAll(e, value);
        }
    }
}

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.numeric;

void main(string[] args)
{
  inputFile = stdin;
  debug inputFile = File(args[1]);
  auto n = next!int;
  auto k = next!int;
  auto a = next!long(n);
  foreach(ref ai; a) ai %= k;
  long mul(long a1, long a2)
  {
    return (a1 * a2) % k;
  }
  auto st = SegmentTree!(long, mul, "mul")(a);
  debug st.mul(0, 0).writeln;
  long ways = 0;
  foreach(i; 0 .. n)
    {
      bool divides(int j) {return st.mul(i, j) == 0;}
      auto end = firstThat!divides(i, n - 1);
      debug writeln("for ", i, " is ", end);
      ways += n - end;
    }
  ways.writeln;
}

// BIN SEARCH
auto firstThat(alias pred, T)(T i, T j)
{
  T first = j + 1;
  while(i <= j)
    {
      debug writeln(i, " ", j);
      auto mid = (i + j) / 2;
      if (pred(mid))
	{
	  first = mid;
	  j = mid - 1;
	}
      else
	{
	  i = mid + 1;
	}
    }
  return first;
}

// Segment Tree
struct SegmentTree(T, alias f, string getMethodName = "get")
{
  static assert(is(typeof((){T x, y; return f(x, y);}()) == T));
  class Node
  {
    size_t low, high;
    size_t length() {return high - low + 1;}
    this(size_t l, size_t h)
    {
      low = l;
      high = h;
    }
    T fValue;
    Node firstHalf, secondHalf;
    bool contains(size_t i, size_t j)
    {
      return max(low, i) <= min(high, j);
    }
    bool inside(size_t i, size_t j)
    {
      return i <= low && high <= j;
    }
  }
  Node _root;
  this(T[] arr)
  {
    _root = new Node(0, arr.length - 1);
    void fill(Node node)
    {
      if (node.length == 1) {node.fValue = arr[node.low]; return;}
      size_t mid = (node.low + node.high) / 2;
      node.firstHalf = new Node(node.low, mid);
      fill(node.firstHalf);
      node.secondHalf = new Node(mid + 1, node.high);
      fill(node.secondHalf);
      node.fValue = f(node.firstHalf.fValue, node.secondHalf.fValue);
    }
    fill(_root);
  }
  mixin(q{alias }, getMethodName, q{ = fRange;});
  T fRange(size_t i, size_t j, Node node = null)
  {
    if (node is null) node = _root;
    debug assert(node !is null);
    debug assert(node.contains(i, j), text(node.low, " ", node.high, " ", i, " ", j));
    if (node.inside(i, j)) return node.fValue;

    debug assert((node.firstHalf !is null && node.firstHalf.contains(i, j))
		 || (node.secondHalf !is null && node.secondHalf.contains(i, j)));

    if (node.firstHalf !is null && node.firstHalf.contains(i, j))
      {
	if (node.secondHalf !is null && node.secondHalf.contains(i, j))
	  return f(fRange(i, j, node.firstHalf), fRange(i, j, node.secondHalf));
	return fRange(i, j, node.firstHalf);
      }
    else
      {
	debug assert(node.secondHalf !is null && node.secondHalf.contains(i, j));
	return fRange(i, j, node.secondHalf);
      }
  }
}

// INPUT

enum InputStyle
  {
    byChunk, byLine
  };
enum inputStyle = InputStyle.byLine;

File inputFile;
string popWord();
static if (inputStyle == InputStyle.byChunk)
  {
    const chunkSize = 1024 * 1024 * 8;
    const wordSize = 4096;
    char[chunkSize] chunkBuff;
    char[] currChunk;
    void renewChunk()
    {
      if (inputFile.eof)
        currChunk = null;
      else
        currChunk = inputFile.rawRead(chunkBuff);
    }
    char[wordSize] wordBuff;
    char[] word;
    string popWord()
    {
      if (currChunk.length == 0)
        renewChunk;
      assert(currChunk.length > 0);
      while (currChunk[0].isWhite)
        {

          currChunk = currChunk[1 .. $];
          if (currChunk.length == 0)
            renewChunk;
        }
      word = wordBuff[0 .. 0];
      while (!currChunk[0].isWhite)
        {
          word.length++;
          word[$ - 1] = currChunk[0];
          currChunk = currChunk[1 .. $];
          if (currChunk.length == 0)
            {
              renewChunk;
              if (currChunk.length == 0)
                return cast(string) word;
            }
        }
      return cast(string) word;
    }
  }
 else
   {
     DList!string _words;
     string popWord()
     {
       while (_words.empty)
         {
           foreach(w; inputFile.readln.split)
             {
               _words.insertBack(w);
             }
         }
       auto word = _words.front;
       _words.removeFront;
       return word;
     }
   }
T next(T)()
{
  return to!T(popWord);
}
auto next(T, S...)(S s)
{
  static if (S.length == 0)
    {
      return to!T(popWord);
    }
  else
    {
      auto res = new typeof(next!T(s[1 .. $]))[](cast(size_t)s[0]);
      foreach(ref elem; res)
        elem = next!T(s[1 .. $]);
      return res;
    }
}

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;

void main() {
    auto s = readln.split.map!(to!int);
    auto N = s[0];
    auto K = s[1];
    auto A = readln.split.map!(to!int).array;

    int p;
    int[] primes;
    int[] primes_n;
    foreach (i; 2..10^^5) {
        if (K % i == 0) {
            p += 1;
            primes ~= i;
            primes_n ~= 0;
        }
        while (K % i == 0) {
            K /= i;
            primes_n[p-1] += 1;
        }
    }

    auto cumsum = new int[][](N+1, p);
    foreach (i; 0..N) {
        auto k = A[i];
        foreach (j; 0..p) {
            while (k % primes[j] == 0) {
                cumsum[i+1][j] += 1;
                k /= primes[j];
            }
        }
    }

    foreach (i; 0..N) {
        cumsum[i+1][] += cumsum[i][];
    }

    long ans = 0;
    auto cs = new int[](p);

    foreach (i; 0..N) {
        int hi = N;
        int lo = i - 1;
        while (hi - lo > 1) {
            int mid = (hi + lo) / 2;
            cs[] = cumsum[mid + 1][] - cumsum[i][];
            if (p.iota.map!(i => cs[i] >= primes_n[i]).all) hi = mid;
            else lo = mid;
        }
        ans += max(N - lo - 1, 0);
    }

    ans.writeln;
}

// tested by Hightail - https://github.com/dj3500/hightail
import std.stdio, std.string, std.conv, std.algorithm;
import std.range, std.array, std.math, std.typecons, std.container, core.bitop;

int n, k;
long[] a;

void main() {
    scan(n, k);

    if (k == 1) {
        writeln(1L * n * (n + 1) / 2L);
        return;
    }

    a = readln.split.to!(long[]);

    auto sg = new SegTree!(long)(a, k);

    long ans;

    foreach (i ; 0 .. n) {
        if (sg.find(i, n, 0, 0, 2^^sg.depth) != 0) break;
        int btm = i, top = n, mid;

        while (top - btm > 1) {
            mid = (top + btm) / 2;

            if (sg.find(i, mid, 0, 0, 2^^sg.depth) == 0) {
                top = mid;
            }
            else {
                btm = mid;
            }
        }

        ans += n + 1 - top;
    }

    writeln(ans);
}

void scan(T...)(ref T args) {
    string[] line = readln.split;
    foreach (ref arg; args) {
        arg = line.front.to!(typeof(arg));
        line.popFront();
    }
    assert(line.empty);
}

void fillAll(R, T)(ref R arr, T value) {
    static if (is(typeof(arr[] = value))) {
        arr[] = value;
    }
    else {
        foreach (ref e; arr) {
            fillAll(e, value);
        }
    }
}

class SegTree(T){
private:
    T[] data;
    int N;
    long mod;
    int depth;

public:
    //int depth;

    this(T[] a, long k){
        N = a.length.to!int;
        mod = k;

        while(2^^depth < N){
            depth++;
        }

        data = new T[](2^^(depth + 1) - 1);

        data[] = 1L;
        data[2^^depth - 1 .. 2^^depth - 1 + N] = a[];

        foreach_reverse (i ; 0 .. 2^^depth - 1) {
            data[i] = 1L * data[2*i + 1] * data[2*i + 2] % mod;
        }
    }

    void update(int i, T x){
        i += 2^^depth - 1;
        data[i] = x;

        while(i > 0){
            i = (i - 1) / 2;
            data[i] = 1L * data[2*i + 1] * data[2*i + 2] % mod;
        }
    }

    T find(int s, int t, int k, int l, int r){
        if (r <= s || t <= l) {
            return 1L;
        }

        if (s <= l && r <= t) {
            return data[k];
        }

        auto vl = find(s, t, 2*k + 1, l, (l + r) / 2);
        auto vr = find(s, t, 2*k + 2, (l + r) / 2, r);

        return 1L * vl * vr % mod;
    }

    void print(){
        stderr.writefln("%(%s %)", data);
    }
}

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.numeric;
import std.range;

void main(string[] args)
{
  inputFile = stdin;
  debug inputFile = File(args[1]);
  auto n = next!int;
  auto k = next!int;
  auto a = next!long(n);
  foreach(ref ai; a) ai %= k;
  auto st = SegmentTree!(long, (x, y) => (x * y) % k, "mul")(a);
  iota(0, n)
    .map!(i => n - firstThat!(j => st.mul(i, j) == 0)(i, n - 1))
    .sum
    .writeln;
}

// BIN SEARCH
auto firstThat(alias pred, T)(T i, T j)
{
  T first = j + 1;
  while(i <= j)
    {
      auto mid = (i + j) / 2;
      if (pred(mid))
	{
	  first = mid;
	  j = mid - 1;
	}
      else
	{
	  i = mid + 1;
	}
    }
  return first;
}

// Segment Tree
struct SegmentTree(T, alias f, string getMethodName = "get")
{
  static assert(is(typeof((){T x, y; return f(x, y);}()) == T));
  class Node
  {
    size_t low, high;
    size_t length() {return high - low + 1;}
    this(size_t l, size_t h)
    {
      low = l;
      high = h;
    }
    T fValue;
    Node firstHalf, secondHalf;
    bool contains(size_t i, size_t j)
    {
      return max(low, i) <= min(high, j);
    }
    bool inside(size_t i, size_t j)
    {
      return i <= low && high <= j;
    }
  }
  Node _root;
  this(T[] arr)
  {
    _root = new Node(0, arr.length - 1);
    void fill(Node node)
    {
      if (node.length == 1) {node.fValue = arr[node.low]; return;}
      size_t mid = (node.low + node.high) / 2;
      node.firstHalf = new Node(node.low, mid);
      fill(node.firstHalf);
      node.secondHalf = new Node(mid + 1, node.high);
      fill(node.secondHalf);
      node.fValue = f(node.firstHalf.fValue, node.secondHalf.fValue);
    }
    fill(_root);
  }
  mixin(q{alias }, getMethodName, q{ = fRange;});
  T fRange(size_t i, size_t j, Node node = null)
  {
    if (node is null) node = _root;
    debug assert(node !is null);
    debug assert(node.contains(i, j), text(node.low, " ", node.high, " ", i, " ", j));
    if (node.inside(i, j)) return node.fValue;

    debug assert((node.firstHalf !is null && node.firstHalf.contains(i, j))
		 || (node.secondHalf !is null && node.secondHalf.contains(i, j)));

    if (node.firstHalf !is null && node.firstHalf.contains(i, j))
      {
	if (node.secondHalf !is null && node.secondHalf.contains(i, j))
	  return f(fRange(i, j, node.firstHalf), fRange(i, j, node.secondHalf));
	return fRange(i, j, node.firstHalf);
      }
    else
      {
	debug assert(node.secondHalf !is null && node.secondHalf.contains(i, j));
	return fRange(i, j, node.secondHalf);
      }
  }
}

// INPUT

enum InputStyle
  {
    byChunk, byLine
  };
enum inputStyle = InputStyle.byLine;

File inputFile;
string popWord();
static if (inputStyle == InputStyle.byChunk)
  {
    const chunkSize = 1024 * 1024 * 8;
    const wordSize = 4096;
    char[chunkSize] chunkBuff;
    char[] currChunk;
    void renewChunk()
    {
      if (inputFile.eof)
        currChunk = null;
      else
        currChunk = inputFile.rawRead(chunkBuff);
    }
    char[wordSize] wordBuff;
    char[] word;
    string popWord()
    {
      if (currChunk.length == 0)
        renewChunk;
      assert(currChunk.length > 0);
      while (currChunk[0].isWhite)
        {

          currChunk = currChunk[1 .. $];
          if (currChunk.length == 0)
            renewChunk;
        }
      word = wordBuff[0 .. 0];
      while (!currChunk[0].isWhite)
        {
          word.length++;
          word[$ - 1] = currChunk[0];
          currChunk = currChunk[1 .. $];
          if (currChunk.length == 0)
            {
              renewChunk;
              if (currChunk.length == 0)
                return cast(string) word;
            }
        }
      return cast(string) word;
    }
  }
 else
   {
     DList!string _words;
     string popWord()
     {
       while (_words.empty)
         {
           foreach(w; inputFile.readln.split)
             {
               _words.insertBack(w);
             }
         }
       auto word = _words.front;
       _words.removeFront;
       return word;
     }
   }
T next(T)()
{
  return to!T(popWord);
}
auto next(T, S...)(S s)
{
  static if (S.length == 0)
    {
      return to!T(popWord);
    }
  else
    {
      auto res = new typeof(next!T(s[1 .. $]))[](cast(size_t)s[0]);
      foreach(ref elem; res)
        elem = next!T(s[1 .. $]);
      return res;
    }
}

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.numeric;
import std.range;

void main(string[] args)
{
  inputFile = stdin;
  debug inputFile = File(args[1]);
  auto n = next!int;
  auto k = next!long;
  auto a = next!long(n);
  foreach(ref ai; a) ai %= k;
  auto st = SegmentTree!(long, (x, y) => (x * y) % k, "mul")(a);
  iota(0, n)
    .map!(i => n - firstThat!(j => st.mul(i, j) == 0)(i, n - 1))
    .sum
    .writeln;
}

// BIN SEARCH
auto firstThat(alias pred, T)(T i, T j)
{
  T first = j + 1;
  while(i <= j)
    {
      auto mid = (i + j) / 2;
      if (pred(mid))
	{
	  first = mid;
	  j = mid - 1;
	}
      else
	{
	  i = mid + 1;
	}
    }
  return first;
}

// Segment Tree
struct SegmentTree(T, alias f, string getMethodName = "get")
{
  static assert(is(typeof((){T x, y; return f(x, y);}()) == T));
  class Node
  {
    size_t low, high;
    size_t length() {return high - low + 1;}
    this(size_t l, size_t h)
    {
      low = l;
      high = h;
    }
    T fValue;
    Node firstHalf, secondHalf;
    bool contains(size_t i, size_t j)
    {
      return max(low, i) <= min(high, j);
    }
    bool inside(size_t i, size_t j)
    {
      return i <= low && high <= j;
    }
  }
  Node _root;
  this(T[] arr)
  {
    _root = new Node(0, arr.length - 1);
    void fill(Node node)
    {
      if (node.length == 1) {node.fValue = arr[node.low]; return;}
      size_t mid = (node.low + node.high) / 2;
      node.firstHalf = new Node(node.low, mid);
      fill(node.firstHalf);
      node.secondHalf = new Node(mid + 1, node.high);
      fill(node.secondHalf);
      node.fValue = f(node.firstHalf.fValue, node.secondHalf.fValue);
    }
    fill(_root);
  }
  mixin(q{alias }, getMethodName, q{ = fRange;});
  T fRange(size_t i, size_t j, Node node = null)
  {
    if (node is null) node = _root;
    debug assert(node !is null);
    debug assert(node.contains(i, j), text(node.low, " ", node.high, " ", i, " ", j));
    if (node.inside(i, j)) return node.fValue;

    debug assert((node.firstHalf !is null && node.firstHalf.contains(i, j))
		 || (node.secondHalf !is null && node.secondHalf.contains(i, j)));

    if (node.firstHalf !is null && node.firstHalf.contains(i, j))
      {
	if (node.secondHalf !is null && node.secondHalf.contains(i, j))
	  return f(fRange(i, j, node.firstHalf), fRange(i, j, node.secondHalf));
	return fRange(i, j, node.firstHalf);
      }
    else
      {
	debug assert(node.secondHalf !is null && node.secondHalf.contains(i, j));
	return fRange(i, j, node.secondHalf);
      }
  }
}

// INPUT

enum InputStyle
  {
    byChunk, byLine
  };
enum inputStyle = InputStyle.byLine;

File inputFile;
string popWord();
static if (inputStyle == InputStyle.byChunk)
  {
    const chunkSize = 1024 * 1024 * 8;
    const wordSize = 4096;
    char[chunkSize] chunkBuff;
    char[] currChunk;
    void renewChunk()
    {
      if (inputFile.eof)
        currChunk = null;
      else
        currChunk = inputFile.rawRead(chunkBuff);
    }
    char[wordSize] wordBuff;
    char[] word;
    string popWord()
    {
      if (currChunk.length == 0)
        renewChunk;
      assert(currChunk.length > 0);
      while (currChunk[0].isWhite)
        {

          currChunk = currChunk[1 .. $];
          if (currChunk.length == 0)
            renewChunk;
        }
      word = wordBuff[0 .. 0];
      while (!currChunk[0].isWhite)
        {
          word.length++;
          word[$ - 1] = currChunk[0];
          currChunk = currChunk[1 .. $];
          if (currChunk.length == 0)
            {
              renewChunk;
              if (currChunk.length == 0)
                return cast(string) word;
            }
        }
      return cast(string) word;
    }
  }
 else
   {
     DList!string _words;
     string popWord()
     {
       while (_words.empty)
         {
           foreach(w; inputFile.readln.split)
             {
               _words.insertBack(w);
             }
         }
       auto word = _words.front;
       _words.removeFront;
       return word;
     }
   }
T next(T)()
{
  return to!T(popWord);
}
auto next(T, S...)(S s)
{
  static if (S.length == 0)
    {
      return to!T(popWord);
    }
  else
    {
      auto res = new typeof(next!T(s[1 .. $]))[](cast(size_t)s[0]);
      foreach(ref elem; res)
        elem = next!T(s[1 .. $]);
      return res;
    }
}

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.numeric;

void main(string[] args)
{
  inputFile = stdin;
  debug inputFile = File(args[1]);
  auto n = next!int;
  auto k = next!int;
  auto a = next!int(n);
  foreach(ref ai; a) ai %= k;
  int mul(int a1, int a2)
  {
    return (a1 * a2) % k;
  }
  auto st = SegmentTree!(int, mul, "mul")(a);
  debug st.mul(0, 0).writeln;
  long ways = 0;
  foreach(i; 0 .. n)
    {
      bool divides(int j) {return st.mul(i, j) == 0;}
      auto end = firstThat!divides(i, n - 1);
      debug writeln("for ", i, " is ", end);
      ways += n - end;
    }
  ways.writeln;
}

// BIN SEARCH
auto firstThat(alias pred, T)(T i, T j)
{
  T first = j + 1;
  while(i <= j)
    {
      debug writeln(i, " ", j);
      auto mid = (i + j) / 2;
      if (pred(mid))
	{
	  first = mid;
	  j = mid - 1;
	}
      else
	{
	  i = mid + 1;
	}
    }
  return first;
}

// Segment Tree
struct SegmentTree(T, alias f, string getMethodName = "get")
{
  static assert(is(typeof((){T x, y; return f(x, y);}()) == T));
  class Node
  {
    size_t low, high;
    size_t length() {return high - low + 1;}
    this(size_t l, size_t h)
    {
      low = l;
      high = h;
    }
    T fValue;
    Node firstHalf, secondHalf;
    bool contains(size_t i, size_t j)
    {
      return max(low, i) <= min(high, j);
    }
    bool inside(size_t i, size_t j)
    {
      return i <= low && high <= j;
    }
  }
  Node _root;
  this(T[] arr)
  {
    _root = new Node(0, arr.length - 1);
    void fill(Node node)
    {
      if (node.length == 1) {node.fValue = arr[node.low]; return;}
      size_t mid = (node.low + node.high) / 2;
      node.firstHalf = new Node(node.low, mid);
      fill(node.firstHalf);
      node.secondHalf = new Node(mid + 1, node.high);
      fill(node.secondHalf);
      node.fValue = f(node.firstHalf.fValue, node.secondHalf.fValue);
    }
    fill(_root);
  }
  mixin(q{alias }, getMethodName, q{ = fRange;});
  T fRange(size_t i, size_t j, Node node = null)
  {
    if (node is null) node = _root;
    debug assert(node !is null);
    debug assert(node.contains(i, j), text(node.low, " ", node.high, " ", i, " ", j));
    if (node.inside(i, j)) return node.fValue;

    debug assert((node.firstHalf !is null && node.firstHalf.contains(i, j))
		 || (node.secondHalf !is null && node.secondHalf.contains(i, j)));

    if (node.firstHalf !is null && node.firstHalf.contains(i, j))
      {
	if (node.secondHalf !is null && node.secondHalf.contains(i, j))
	  return f(fRange(i, j, node.firstHalf), fRange(i, j, node.secondHalf));
	return fRange(i, j, node.firstHalf);
      }
    else
      {
	debug assert(node.secondHalf !is null && node.secondHalf.contains(i, j));
	return fRange(i, j, node.secondHalf);
      }
  }
}

// INPUT

enum InputStyle
  {
    byChunk, byLine
  };
enum inputStyle = InputStyle.byLine;

File inputFile;
string popWord();
static if (inputStyle == InputStyle.byChunk)
  {
    const chunkSize = 1024 * 1024 * 8;
    const wordSize = 4096;
    char[chunkSize] chunkBuff;
    char[] currChunk;
    void renewChunk()
    {
      if (inputFile.eof)
        currChunk = null;
      else
        currChunk = inputFile.rawRead(chunkBuff);
    }
    char[wordSize] wordBuff;
    char[] word;
    string popWord()
    {
      if (currChunk.length == 0)
        renewChunk;
      assert(currChunk.length > 0);
      while (currChunk[0].isWhite)
        {

          currChunk = currChunk[1 .. $];
          if (currChunk.length == 0)
            renewChunk;
        }
      word = wordBuff[0 .. 0];
      while (!currChunk[0].isWhite)
        {
          word.length++;
          word[$ - 1] = currChunk[0];
          currChunk = currChunk[1 .. $];
          if (currChunk.length == 0)
            {
              renewChunk;
              if (currChunk.length == 0)
                return cast(string) word;
            }
        }
      return cast(string) word;
    }
  }
 else
   {
     DList!string _words;
     string popWord()
     {
       while (_words.empty)
         {
           foreach(w; inputFile.readln.split)
             {
               _words.insertBack(w);
             }
         }
       auto word = _words.front;
       _words.removeFront;
       return word;
     }
   }
T next(T)()
{
  return to!T(popWord);
}
auto next(T, S...)(S s)
{
  static if (S.length == 0)
    {
      return to!T(popWord);
    }
  else
    {
      auto res = new typeof(next!T(s[1 .. $]))[](cast(size_t)s[0]);
      foreach(ref elem; res)
        elem = next!T(s[1 .. $]);
      return res;
    }
}


import std.algorithm;
import std.conv;
import std.exception;
import std.math;
import std.numeric;
import std.range;
import std.stdio;
import std.string;
import std.typecons;

void main ()
{
	int n, m;
	while (readf (" %s %s ", &n, &m) > 0)
	{
		auto a = new string [n];
		foreach (i; 0..n)
		{
			a[i] = readln ().strip ();
		}

		auto b = new int [] [] (m, n);
		foreach (j; 0..m)
		{
			foreach (i; 0..n)
			{
				b[j][i] = a[i][j] - '0';
			}
		}

		int res = 0;
		auto c = new int [m + 1];
		foreach (j; 0..m)
		{
			foreach (i; 0..n)
			{
				if (b[j][i] != 0)
				{
					if (j > 0)
					{
						b[j][i] = b[j - 1][i] + 1;
					}
				}
			}

			c[] = 0;
			foreach (i; 0..n)
			{
				c[b[j][i]]++;
			}

			int w;
			int h = 0;
			foreach_reverse (k; 0..m + 1)
			{
				foreach (q; 0..c[k])
				{
					w = k;
					h++;
					debug {writeln (w, ' ', h);}
					res = max (res, w * h);
				}
			}
		}

		writeln (res);
	}
}

import std.stdio, std.string;

void solve(int n, int m, char[][] mat)
{
    auto cnt = new int[m + 1];
    auto len = new int[n];
    auto prelen = new int[n];
    int ans = 0;
    foreach (i; 0 .. m)
    {
        int[] modify;
        foreach (j; 0 .. n)
        {
            len[j] = 0;
            if (mat[j][i] == '1')
            {
                if (prelen[j])
                {
                    len[j] = prelen[j] + 1;
                }
                else
                {
                    len[j] = 1;
                }
            }
            if (!cnt[len[j]]) modify ~= len[j];
            ++ cnt[len[j]];
        }
        int count = 0;
        for (int j = i + 1; j > 0; -- j)
        {
            if (cnt[j])
            {
                count += cnt[j];
                if (j * count > ans) ans = j * count;
            }
        }
        foreach (val; modify) cnt[val] = 0;
        foreach (j; 0 .. n) prelen[j] = len[j];
    }
    writeln(ans);
}

void main(string[] args)
{
    int n, m;
    while (scanf("%d%d", &n, &m) == 2)
    {
        auto mat = new char[][n];
        stdin.readln(mat[0]);
        foreach (i; 0 .. n) stdin.readln(mat[i]);
        solve(n, m, mat);
    }
}

import std.stdio, std.string;
import std.algorithm;

void solve(int n, int m, char[][] mat)
{
    auto cnt = new int[m + 1];
    auto len = new int[n];
    auto prelen = new int[n];
    int ans = 0;
    foreach (i; 0 .. m)
    {
        //int[] modify;
        foreach (j; 0 .. n)
        {
            len[j] = 0;
            if (mat[j][i] == '1')
            {
                if (prelen[j])
                {
                    len[j] = prelen[j] + 1;
                }
                else
                {
                    len[j] = 1;
                }
            }
            //if (!cnt[len[j]]) modify ~= len[j];
            ++ cnt[len[j]];
        }
        int count = 0;
        for (int j = i + 1; j > 0; -- j)
        {
            if (cnt[j])
            {
                count += cnt[j];
                if (j * count > ans) ans = j * count;
            }
        }
        fill(cnt, 0);
        //foreach (val; modify) cnt[val] = 0;
        foreach (j; 0 .. n) prelen[j] = len[j];
    }
    writeln(ans);
}

void main(string[] args)
{
    int n, m;
    while (scanf("%d%d", &n, &m) == 2)
    {
        auto mat = new char[][n];
        stdin.readln(mat[0]);
        foreach (i; 0 .. n) stdin.readln(mat[i]);
        solve(n, m, mat);
    }
}

import std.stdio, std.string;
import std.algorithm;

void solve(int n, int m, char[][] mat)
{
    auto cnt = new int[m + 1];
    auto len = new int[n];
    auto prelen = new int[n];
    auto modify = new int[m + 1];
    int ans = 0;
    foreach (i; 0 .. m)
    {
        //int[] modify;
        int midx = 0;
        foreach (j; 0 .. n)
        {
            len[j] = 0;
            if (mat[j][i] == '1')
            {
                len[j] = 1;
                if (prelen[j])
                {
                    len[j] += prelen[j];
                }
            }
            if (!cnt[len[j]]) modify[midx ++] = len[j];
            ++ cnt[len[j]];
        }
        int count = 0;
        for (int j = i + 1; j > 0; -- j)
        {
            if (cnt[j])
            {
                count += cnt[j];
                if (j * count > ans) ans = j * count;
            }
        }
        //fill(cnt, 0);
        for (int j = 0; j < midx; ++ j) cnt[modify[j]] = 0;
        //foreach (val; modify) cnt[val] = 0;
        foreach (j; 0 .. n) prelen[j] = len[j];
    }
    writeln(ans);
}

void main(string[] args)
{
    int n, m;
    while (scanf("%d%d", &n, &m) == 2)
    {
        auto mat = new char[][n];
        stdin.readln(mat[0]);
        foreach (i; 0 .. n) stdin.readln(mat[i]);
        solve(n, m, mat);
    }
}


void main() { runSolver(); }

void problem() {
  auto QN = scan!long;

  auto solve() {
    foreach(_; 0..QN) {
      auto N = scan!int;
      auto A = scan!long(N);

      (A.maxElement - A.minElement).writeln;
    }
  }

  outputForAtCoder(&solve);
}

// ----------------------------------------------

import std.stdio, std.conv, std.array, std.string, std.algorithm, std.container, std.range, core.stdc.stdlib, std.math, std.typecons, std.numeric, std.traits, std.functional, std.bigint, std.datetime.stopwatch, core.time, core.bitop;
T[][] combinations(T)(T[] s, in long m) {   if (!m) return [[]];   if (s.empty) return [];   return s[1 .. $].combinations(m - 1).map!(x => s[0] ~ x).array ~ s[1 .. $].combinations(m); }
string scan(){ static string[] ss; while(!ss.length) ss = readln.chomp.split; string res = ss[0]; ss.popFront; return res; }
T scan(T)(){ return scan.to!T; }
T[] scan(T)(long n){ return n.iota.map!(i => scan!T()).array; }
void deb(T ...)(T t){ debug writeln(t); }
alias Point = Tuple!(long, "x", long, "y");
Point invert(Point p) { return Point(p.y, p.x); }
long[] divisors(long n) { long[] ret; for (long i = 1; i * i <= n; i++) { if (n % i == 0) { ret ~= i; if (i * i != n) ret ~= n / i; } } return ret.sort.array; }
bool chmin(T)(ref T a, T b) { if (b < a) { a = b; return true; } else return false; }
bool chmax(T)(ref T a, T b) { if (b > a) { a = b; return true; } else return false; }
string charSort(alias S = "a < b")(string s) { return (cast(char[])((cast(byte[])s).sort!S.array)).to!string; }
ulong comb(ulong a, ulong b) { if (b == 0) {return 1;}else{return comb(a - 1, b - 1) * a / b;}}
string toAnswerString(R)(R r) { return r.map!"a.to!string".joiner(" ").array.to!string; }
struct ModInt(uint MD) if (MD < int.max) {ulong v;this(string v) {this(v.to!long);}this(int v) {this(long(v));}this(long v) {this.v = (v%MD+MD)%MD;}void opAssign(long t) {v = (t%MD+MD)%MD;}static auto normS(ulong x) {return (x<MD)?x:x-MD;}static auto make(ulong x) {ModInt m; m.v = x; return m;}auto opBinary(string op:"+")(ModInt r) const {return make(normS(v+r.v));}auto opBinary(string op:"-")(ModInt r) const {return make(normS(v+MD-r.v));}auto opBinary(string op:"*")(ModInt r) const {return make((ulong(v)*r.v%MD).to!ulong);}auto opBinary(string op:"^^", T)(T r) const {long x=v;long y=1;while(r){if(r%2==1)y=(y*x)%MD;x=x^^2%MD;r/=2;} return make(y);}auto opBinary(string op:"/")(ModInt r) const {return this*memoize!inv(r);}static ModInt inv(ModInt x) {return x^^(MD-2);}string toString() const {return v.to!string;}auto opOpAssign(string op)(ModInt r) {return mixin ("this=this"~op~"r");}}
alias MInt1 = ModInt!(10^^9 + 7);
alias MInt9 = ModInt!(998_244_353);
void outputForAtCoder(T)(T delegate() fn) {
  static if (is(T == float) || is(T == double) || is(T == real)) "%.16f".writefln(fn());
  else static if (is(T == void)) fn();
  else static if (is(T == string)) fn().writeln;
  else static if (isInputRange!T) {
    static if (!is(string == ElementType!T) && isInputRange!(ElementType!T)) foreach(r; fn()) r.toAnswerString.writeln;
    else foreach(r; fn()) r.writeln;
  }
  else fn().writeln;
}
void runSolver() {
  enum BORDER = "==================================";
  debug { BORDER.writeln; while(!stdin.eof) { "<<< Process time: %s >>>".writefln(benchmark!problem(1)); BORDER.writeln; } }
  else problem();
}
enum YESNO = [true: "Yes", false: "No"];

// -----------------------------------------------

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;

void main()
{
  foreach (casenum ; 1 .. readln.strip.to!int + 1) {
    long n;
    readf!" %d "(n);
    auto a = readln.splitter.map!(to!long).array;
    writeln(a.maxElement - a.minElement);
  }
}

import std;

void main () {
    immutable tests = (){ uint t; readf!"%s\n"(t); return t; }();

    foreach (test_index; 0 .. tests) {
        readln();
        const pair =
            readln.chomp
            .split(' ')
            .map!(str => to!int(str))
            .fold!(min, max);

        writeln(pair[1] - pair[0]);
    }
}
// ""


import std.stdio;
import std.math;
import std.numeric;
import std.container;
import std.typecons;
import core.stdc.stdio : scanf;
import std.conv;
import std.array;
import std.string;
import std.range;
import std.algorithm;

T read(T)() { return readln.chomp.to!T; }
T[] readarray(T)() { return readln.chomp.split(" ").map!(to!T).array; }

void main() {
    int T = read!int;
    foreach (t; 0 .. T) solve();
}

void solve() {
    int N, K; readf("%d %d\n", &N, &K);
    auto P = readarray!int;
    foreach (ref p; P) p--;
    auto G = new int[][N];
    for (int i = 1; i < N; i++) {
        int p = P[i-1];
        G[p] ~= i;
    }
    auto C = readarray!long;

    long[Tuple!(int,int)] cache;
    long f(int v, int m) {
        if (G[v].empty) {
            return C[v] * m;
        } else {
            long r = C[v] * m;
            auto key = tuple(v, m);
            if (key in cache) return cache[key];
            int a = m / (G[v].length);
            int rem = m - a * G[v].length;
            auto xs = G[v].map!(u => f(u, a)).array;
            long sx = xs.reduce!"a+b";
            if (rem > 0) {
                auto ys = G[v].map!(u => f(u, a+1)).array;
                auto ds = iota(G[v].length).array.map!(i => ys[i] - xs[i]).array.sort!"a > b".array;
                long add = 0;
                for (int j = 0; j < rem; j++) {
                    add += ds[j];
                }
                r += sx + add;
                return cache[key] = r;
            } else {
                r += sx;
                return cache[key] = r;
            }
        }
    }
    writeln(f(0, K));
}

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)); }

int N;
long K;
int[] P;
long[] S;

int[][] graph;

int[] lens;
long[3][] kss, fss;
long solve(int u, long k) {
  foreach (j; 0 .. lens[u]) {
    if (kss[u][j] == k) {
      return fss[u][j];
    }
  }

  long ret = S[u] * k;
  const deg = cast(int)(graph[u].length);
  if (deg) {
    const q = k / deg;
    const r = k % deg;
    auto ds = new long[deg];
    foreach (j; 0 .. deg) {
      const v = graph[u][j];
      const res0 = solve(v, q);
      ret += res0;
      if (r) {
        const res1 = solve(v, q + 1);
        ds[j] = res1 - res0;
      }
    }
    ds.sort;
    ret += ds[deg - cast(int)(r) .. deg].sum;
  }

  assert(lens[u] < 3);
  kss[u][lens[u]] = k;
  fss[u][lens[u]] = ret;
  ++lens[u];
  return ret;
}

void main() {
  try {
    for (; ; ) {
      const numCases = readInt;
      foreach (caseId; 0 .. numCases) {
        N = readInt;
        K = readLong;
        P = new int[N];
        P[0] = -1;
        foreach (u; 1 .. N) {
          P[u] = readInt - 1;
        }
        S = new long[N];
        foreach (u; 0 .. N) {
          S[u] = readLong;
        }

        graph = new int[][N];
        foreach (u; 1 .. N) {
          graph[P[u]] ~= u;
        }

        lens = new int[N];
        kss = new long[3][N];
        fss = new long[3][N];
        const ans = solve(0, K);
        writeln(ans);
      }
    }
  } catch (EOFException e) {
  }
}

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

void main ()
{
	auto tests = readln.strip.to !(int);
	foreach (test; 0..tests)
	{
		int n, k;
		readf !(" %s %s") (n, k);
		readln;
		auto p = [0] ~ readln.splitter.map !(to !(int)).array;
		p[] -= 1;
		auto s = readln.splitter.map !(to !(int)).array;

		auto adj = new int [] [n];
		auto d = new int [n];
		foreach (i; 1..n)
		{
			adj[p[i]] ~= i;
			d[p[i]] += 1;
		}

		alias Pair = Tuple !(int, q{v}, int, q{num});
		long [Pair] mem;

		long recur (int v, int num)
		{
			auto coord = Pair (v, num);
			if (coord !in mem)
			{
				long res = s[v] * 1L * num;
				if (d[v] > 0)
				{
					int lo = num / d[v];
					int hi = (num + d[v] - 1) / d[v];
					long [] vLo;
					long [] vHi;
					foreach (u; adj[v])
					{
						vLo ~= recur (u, lo);
						vHi ~= recur (u, hi);
						res += vLo.back;
					}
					auto p = d[v].iota.array;
					p.schwartzSort !(i => vHi[i] - vLo[i],
					    q{a > b}, SwapStrategy.stable);
					int rem = num % d[v];
					foreach (i; p[0..rem])
					{
						res += (vHi[i] - vLo[i]);
					}
				}
				mem[coord] = res;
			}
			return mem[coord];
		}

		writeln (recur (0, k));
	}
}


import core.thread;
import std.conv, std.stdio, std.string;
import std.algorithm, std.array, std.bigint, std.container, std.math, std.range, std.regex;

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

//	chmin/chmax
void chmin(T)(ref T t, in T f) { if (t > f) t = f; }
void chmax(T)(ref T t, in T f) { if (t < f) t = f; }

//	Pair
struct Pair(S, T) {
	S x; T y;
	int opCmp(    const Pair p) const { return (x < p.x) ? -1 : (x > p.x) ? +1 : (y < p.y) ? -1 : (y > p.y) ? +1 : 0; }
	int opCmp(ref const Pair p) const { return (x < p.x) ? -1 : (x > p.x) ? +1 : (y < p.y) ? -1 : (y > p.y) ? +1 : 0; }
	string toString() const { return "(" ~ to!string(x) ~ ", " ~ to!string(y) ~ ")"; }
}
auto pair(S, T)(inout(S) x, inout(T) y) { return Pair!(S, T)(x, y); }

//	Array
int binarySearch(T)(in T[] as, in bool delegate(T) test) { int low = -1, upp = as.length; for (; low + 1 < upp; ) { int mid = (low + upp) >> 1; (test(as[mid]) ? low : upp) = mid; } return upp; }
int lowerBound(T)(in T[] as, in T val) { return as.binarySearch((T a) { return (a <  val); }); }
int upperBound(T)(in T[] as, in T val) { return as.binarySearch((T a) { return (a <= val); }); }
T[] unique(T)(in T[] as) { T[] bs; foreach (a; as) if (bs.empty || bs[$ - 1] != a) bs ~= a; return bs; }

int root(int[] uf, int u) {
	return (uf[u] < 0) ? u : (uf[u] = uf.root(uf[u]));
}
bool conn(int[] uf, int u, int v) {
	u = uf.root(u);
	v = uf.root(v);
	if (u == v) return 0;
	if (uf[u] > uf[v]) swap(u, v);
	uf[u] += uf[v];
	uf[v] = u;
	return 1;
}

int N, M;
int[] A, B;

void main(string[] args) {
	try {
	for (; ; ) {
		N = readInt;
		M = readInt;
		A = new int[M];
		B = new int[M];
		foreach (i; 0 .. M) {
			A[i] = readInt - 1;
			B[i] = readInt - 1;
		}

		int[] uf = new int[N];
		uf[] = -1;
		foreach (i; 0 .. M) {
			uf.conn(A[i], B[i]);
		}

		long ans = 1;
		foreach (u; 0 .. N) {
			if (!(uf[u] < 0)) {
				ans *= 2;
			}
		}
		writeln(ans);
	}
	} catch (EOFException) {}
}

import std.stdio;
import std.c.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;
import std.c.string;
import std.regex;
import std.typecons;

void main() {
    int N, M; scanf("%d %d\n", &N, &M);
    bool[][] G = new bool[][](N + 1, N + 1);
    foreach (ref L; G) L[] = false;
    foreach (i; 0 .. M) {
        int x, y; scanf("%d %d\n", &x, &y);
        G[x][y] = G[y][x] = true;
    }

    // 連結グラフの個数
    int Count() {
        int Ret = 0;
        bool[] used = new bool[N + 1];

        void dfs(int x) {
            used[x] = true;
            for (int i = 1; i <= N; i++) {
                if (!used[i] && G[x][i]) {
                    dfs(i);
                }
            }
        }

        for (int i = 1; i <= N; i++) {
            if (!used[i]) {
                dfs(i);
                Ret++;
            }
        }
        return Ret;
    }

    writeln( 1L << (N - Count()) );
}

import std.stdio;
import std.c.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;
import std.c.string;
import std.regex;
import std.typecons;

void main() {
    int N, M; scanf("%d %d\n", &N, &M);
    bool[][] G = new bool[][](N + 1, N + 1);
    foreach (ref L; G) L[] = false;
    foreach (i; 0 .. M) {
        int x, y; scanf("%d %d\n", &x, &y);
        G[x][y] = G[y][x] = true;
    }

    // 連結グラフの個数
    int Count() {
        int Ret = 0;
        bool[] used = new bool[N + 1];

        void dfs(int x) {
            used[x] = true;
            for (int i = 1; i <= N; i++) {
                if (!used[i]) {
                    dfs(i);
                }
            }
        }

        for (int i = 1; i <= N; i++) {
            if (!used[i]) {
                dfs(i);
                Ret++;
            }
        }
        return Ret;
    }

    writeln( 1L << (N - Count()) );
}

import std.stdio;

void main()
{
    int ctl;
    readf("%s",&ctl);
    if(ctl == -1){
      run_tests();
    } else{
      run_instance(ctl);
    }

}

// void debug(T...)(T args){
//
// }
// int DEBUG = false;
//
// void debug(){
//   if(DEBUG){
//
//   }
// }

void run_instance(int ctl){
    int n = ctl;
    int m; readf(" %s\n",&m);
    auto graph = new G(n);

    for(int i = 0; i < m; i++){
        int s; readf("%s ",&s);
        int d; readf("%s ",&d);
        graph.add_vertex(s,d);
    }

    int r = calculate(n,m,graph);
    writefln("%s",r);
}

int calculate(int n, int m, G graph){
  int c = graph.components();
  int x = std.math.pow(2,n-c);
  //writefln("CX %s",c);
  return x;
}

void run_tests(){
  int[][] rs;
  rs ~= [[calculate(1,0,new G(1,[])),1]];
  rs ~= [[calculate(2,1,new G(2,[1,2])),2]];
  rs ~= [[calculate(3,2,new G(3,[1,2,2,3])),4]];
  rs ~= [[calculate(10,10,new G(10,[1,8,4,10,4,6,5,10,2,3,1,7,3,4,3,6,6,9,3,7])),128]];
  rs ~= [[calculate(10,10,new G(10,[])),1]];

  int i = 0;
  bool failed = false;
  foreach(int[] r;rs){
    if(r[0] != r[1]){
      failed = true;
      //writefln("%s Failed %s != %s",i,r[0],r[1]);
    }
    i++;
  }

  if(!failed){
    writefln("OK");
  }
}

class G{
  int[][] vertex;
  int[] visited;
  ulong v_count = 0;

  this(int v_count){
    //writefln("NEW %s",v_count);
    for (int i = 0; i< v_count; i++){
      this.vertex ~= [[]];
      this.visited ~= 0;
    }
    this.v_count = v_count;
  }

  this(int n, int[] list){
    this(n);
    for (int i = 1; i < list.length; i += 2){
        this.add_vertex(list[i-1],list[i]);
    }
  }

  int[] conn(int v){
    return this.vertex[v];
  }

  void add_vertex(int s,int d){
    //writefln("%s-%s",s,d);
    vertex[s-1] ~= [d-1];
  }

  int components(){
    int cmp = 0;
    int[] q;

    int cur = 0;
    for(int v = 0; v < this.v_count; v++){
      if(this.visited[v] == 0){
        //writefln("*Visited %s (%s)",v+1,this.vertex[v].length);
        this.visited[v] = 1;
        cmp++;
        q ~= this.vertex[v];

        while(q.length > cur){
          v = q[cur];
          cur++;
          if ( this.visited[v] == 0 ){
            //writefln("Visited %s (%s)",v+1,this.vertex[v].length);
            this.visited[v] = 1;
            q ~= this.vertex[v];
          }
        }
      }
    }

    return cmp;
  }
}

import std.stdio;

void main()
{
    int ctl;
    readf("%s",&ctl);
    if(ctl == -1){
      run_tests();
    } else{
      run_instance(ctl);
    }

}

// void debug(T...)(T args){
//
// }
// int DEBUG = false;
//
// void debug(){
//   if(DEBUG){
//
//   }
// }

void run_instance(int ctl){
    int n = ctl;
    int m; readf(" %s\n",&m);
    auto graph = new G(n);

    for(int i = 0; i < m; i++){
        int s; readf("%s ",&s);
        int d; readf("%s ",&d);
        graph.add_vertex(s,d);
    }

    int r = calculate(n,m,graph);
    writefln("%s",r);
}

int calculate(int n, int m, G graph){
  int c = graph.components();
  int x = std.math.pow(2,n-c);
  //writefln("CX %s",c);
  return x;
}

void run_tests(){
  int[][] rs;
  rs ~= [[calculate(1,0,new G(1,[])),1]];
  rs ~= [[calculate(2,1,new G(2,[1,2])),2]];
  rs ~= [[calculate(3,2,new G(3,[1,2,2,3])),4]];
  rs ~= [[calculate(10,10,new G(10,[1,8,4,10,4,6,5,10,2,3,1,7,3,4,3,6,6,9,3,7])),512]];
  rs ~= [[calculate(10,10,new G(10,[])),1]];

  int i = 0;
  bool failed = false;
  foreach(int[] r;rs){
    if(r[0] != r[1]){
      failed = true;
      writefln("%s Failed %s != %s",i,r[0],r[1]);
    }
    i++;
  }

  if(!failed){
    writefln("OK");
  }
}

class G{
  int[][] vertex;
  int[] visited;
  ulong v_count = 0;

  this(int v_count){
    //writefln("NEW %s",v_count);
    for (int i = 0; i< v_count; i++){
      this.vertex ~= [[]];
      this.visited ~= 0;
    }
    this.v_count = v_count;
  }

  this(int n, int[] list){
    this(n);
    for (int i = 1; i < list.length; i += 2){
        this.add_vertex(list[i-1],list[i]);
    }
  }

  int[] conn(int v){
    return this.vertex[v];
  }

  void add_vertex(int s,int d){
    //writefln("%s-%s",s,d);
    vertex[s-1] ~= [d-1];
    vertex[d-1] ~= [s-1];
  }

  int components(){
    int cmp = 0;
    int[] q;

    int cur = 0;
    for(int v = 0; v < this.v_count; v++){
      if(this.visited[v] == 0){
        //writefln("*Visited %s (%s)",v+1,this.vertex[v].length);
        this.visited[v] = 1;
        cmp++;
        q ~= this.vertex[v];

        while(q.length > cur){
          v = q[cur];
          cur++;
          if ( this.visited[v] == 0 ){
            //writefln("Visited %s (%s)",v+1,this.vertex[v].length);
            this.visited[v] = 1;
            q ~= this.vertex[v];
          }
        }
      }
    }

    return cmp;
  }
}

import std.stdio;

void main()
{
    int ctl;
    readf("%s",&ctl);
    if(ctl == -1){
      run_tests();
    } else{
      run_instance(ctl);
    }

}

void run_instance(int ctl){
    int n = ctl;
    int m; readf(" %s\n",&m);
    auto graph = new G(n);

    for(int i = 0; i < m; i++){
        int s; readf("%s ",&s);
        int d; readf("%s ",&d);
        graph.add_vertex(s,d);
    }

    int r = calculate(n,m,graph);
    writefln("%s",r);
}

int calculate(int n, int m, G graph){
  int c = graph.components();
  int x = std.math.pow(2,n-c);
  //writefln("CX %s",c);
  return x;
}

void run_tests(){
  int[][] rs;
  rs ~= [[calculate(1,0,new G(1,[])),1]];
  rs ~= [[calculate(2,1,new G(2,[1,2])),2]];
  rs ~= [[calculate(3,2,new G(3,[1,2,2,3])),4]];
  int i = 0;
  bool failed = false;
  foreach(int[] r;rs){
    if(r[0] != r[1]){
      failed = true;
      writefln("%s Failed %s != %s",i,r[0],r[1]);
    }
    i++;
  }

  if(!failed){
    writefln("OK");
  }
}

class G{
  int[][] vertex;
  int[] visited;
  ulong v_count = 0;

  this(int v_count){
    for (int i = 0; i< v_count; i++){
      this.vertex ~= [[]];
      this.visited ~= 0;
    }
    this.v_count = v_count;
  }

  this(int n, int[] list){
    this(n);
    for (int i = 1; i < list.length; i++){
        this.add_vertex(list[i-1],list[i]);
    }
  }

  int[] conn(int v){
    return this.vertex[v];
  }

  void add_vertex(int s,int d){
    vertex[s-1] ~= d-1;
  }

  int components(){
    int cmp = 0;
    int[] q;

    int cur = 0;
    for(int v = 0; v < this.v_count; v++){
      if(this.visited[v] == 0){
        this.visited[v] = 1;
        cmp++;
        q ~= this.vertex[v];

        while(q.length > cur){
          v = q[cur];
          cur++;

          if ( this.visited[v] == 0 ){
            this.visited[v] = 1;
            q ~= this.vertex[v];
          }
        }
      }
    }

    return cmp;
  }
}

import std.stdio;

void main()
{
    int ctl;
    readf("%s",&ctl);
    if(ctl == -1){
      run_tests();
    } else{
      run_instance(ctl);
    }

}

// void debug(T...)(T args){
//
// }
// int DEBUG = false;
//
// void debug(){
//   if(DEBUG){
//
//   }
// }

void run_instance(int ctl){
    int n = ctl;
    int m; readf(" %s\n",&m);
    auto graph = new G(n);

    for(int i = 0; i < m; i++){
        int s; readf("%s ",&s);
        int d; readf("%s ",&d);
        graph.add_vertex(s,d);
    }

    int r = calculate(n,m,graph);
    writefln("%s",r);
}

int calculate(int n, int m, G graph){
  int c = graph.components();
  int x = std.math.pow(2,n-c);
  writefln("CX %s",c);
  return x;
}

void run_tests(){
  int[][] rs;
  rs ~= [[calculate(1,0,new G(1,[])),1]];
  rs ~= [[calculate(2,1,new G(2,[1,2])),2]];
  rs ~= [[calculate(3,2,new G(3,[1,2,2,3])),4]];
  rs ~= [[calculate(10,10,new G(10,[1,8,4,10,4,6,5,10,2,3,1,7,3,4,3,6,6,9,3,7])),512]];
  rs ~= [[calculate(20,20,new G(20,[6,8,13,20,7,13,6,17,5,15,1,12,5,5,17,5,14,6,14,12,20,7,20,1,6,1,7,2,19,14,17,1,10,11,15,9,18,2,12])),32768]];

  int i = 0;
  bool failed = false;
  foreach(int[] r;rs){
    if(r[0] != r[1]){
      failed = true;
      writefln("%s Failed %s is NOT %s",i,r[0],r[1]);
    }
    i++;
  }

  if(!failed){
    writefln("OK");
  }
}

class G{
  int[][] vertex;
  int[] visited;
  ulong v_count = 0;

  this(int v_count){
    //writefln("NEW %s",v_count);
    for (int i = 0; i< v_count; i++){
      this.vertex ~= [[]];
      this.visited ~= 0;
    }
    this.v_count = v_count;
  }

  this(int n, int[] list){
    this(n);
    for (int i = 1; i < list.length; i += 2){
        this.add_vertex(list[i-1],list[i]);
    }
  }

  int[] conn(int v){
    return this.vertex[v];
  }

  void add_vertex(int s,int d){
    //writefln("%s-%s",s,d);
    vertex[s-1] ~= [d-1];
    vertex[d-1] ~= [s-1];
  }

  int components(){
    int cmp = 0;
    int[] q;

    int cur = 0;
    for(int v = 0; v < this.v_count; v++){
      if(this.visited[v] == 0){
        //writefln("*Visited %s (%s)",v+1,this.vertex[v].length);
        this.visited[v] = 1;
        cmp++;
        q ~= this.vertex[v];

        while(q.length > cur){
          v = q[cur];
          cur++;
          if ( this.visited[v] == 0 ){
            //writefln("Visited %s (%s)",v+1,this.vertex[v].length);
            this.visited[v] = 1;
            q ~= this.vertex[v];
          }
        }
      }
    }

    return cmp;
  }
}


import std.stdio, std.string;
import std.typecons;
import std.algorithm;

struct XD
{
    int c;
    int d;
}

long saiki(int idx, int rem, long[][] dp, XD[][] b)
{
    auto res = dp[idx][rem];
    if (res != -1) return res;
    if (idx == cast(int)b.length)
    {
        dp[idx][rem] = 0;
        return 0;
    }
    auto one = new int[3];
    fill(one, -1);
    auto two = -1;
    auto three = -1;
    foreach (i; 0 .. b[idx].length)
    {
        auto d = b[idx][i].d;
        if (b[idx][i].c == 1)
        {
            foreach (j; 0 .. 3)
            {
                if (d >= one[j])
                {
                    for (int k = 2; k > j; -- k)
                    {
                        one[k] = one[k - 1];
                    }
                    one[j] = d;
                    break;
                }
            }
        }
        else if (b[idx][i].c == 2)
        {
            if (d > two) two = d;
        }
        else
        {
            if (d > three) three = d;
        }
    }
    res = saiki(idx + 1, rem, dp, b);
    bool twice = (rem == 9);
    long ret = saiki(idx + 1, (rem + 1) % 10, dp, b);
    if (three != -1)
    {
        if (twice) res = max(res, ret + (three << 1));
        else res = max(res, ret + three);
    }
    if (two != -1)
    {
        if (twice) res = max(res, ret + (two << 1));
        else res = max(res, ret + two);
    }
    if (one[0] != -1)
    {
        if (twice) res = max(res, ret + (one[0] << 1));
        else res = max(res, ret + one[0]);
    }
    twice = (rem == 8 || rem == 9);
    ret = saiki(idx + 1, (rem + 2) % 10, dp, b);
    if (one[1] != -1)
    {
        if (twice) res = max(res, ret + (one[0] << 1) + one[1]);
        else res = max(res, ret + one[0] + one[1]);
    }
    if (one[0] != -1 && two != -1)
    {
        if (twice) res = max(res, ret + (max(one[0], two) << 1) + min(one[0], two));
        else res = max(res, ret + one[0] + two);
    }
    if (one[2] != -1)
    {
        twice = (rem >= 7 && rem < 10);
        ret = saiki(idx + 1, (rem + 3) % 10, dp, b);
        if (twice) res = max(res, ret + (one[0] << 1) + one[1] + one[2]);
        else res = max(res, ret + one[0] + one[1] + one[2]);
    }
    dp[idx][rem] = res;
    return res;
}

void solve(XD[][] b)
{
    auto n = cast(int)b.length;
    auto dp = new long[][](n + 1, 10);
    foreach (i; 0 .. n + 1) fill(dp[i], -1);
    auto ans = saiki(0, 0, dp, b);
    writeln(ans);
}

int main(string[] args)
{
    int n;
    while (readf("%d\n", &n) == 1)
    {
        auto b = new XD[][n];
        foreach (i; 0 .. n)
        {
            int k;
            readf("%d\n", &k);
            b[i] = new XD[k];
            foreach (j; 0 .. k)
            {
                readf("%d %d\n", &b[i][j].c, &b[i][j].d);
            }
        }
        solve(b);
    }
    return 0;
}

import std.stdio, std.string;
import std.typecons;
import std.algorithm;

long saiki(int idx, int rem, long[][] dp, Tuple!(int, int)[][] b)
{
    auto res = dp[idx][rem];
    if (res != -1) return res;
    if (idx == cast(int)b.length)
    {
        dp[idx][rem] = 0;
        return 0;
    }
    auto one = new int[3];
    fill(one, -1);
    auto two = -1;
    auto three = -1;
    foreach (i; 0 .. b[idx].length)
    {
        auto d = b[idx][i][1];
        if (b[idx][i][0] == 1)
        {
            foreach (j; 0 .. 3)
            {
                if (d >= one[j])
                {
                    for (int k = 2; k > j; -- k) one[k] = one[k - 1];
                    one[j] = d;
                    break;
                }
            }
        }
        else if (b[idx][i][0] == 2)
        {
            if (d > two) two = d;
        }
        else
        {
            if (d > three) three = d;
        }
    }
    res = saiki(idx + 1, rem, dp, b);
    bool twice = (rem == 9);
    long ret = saiki(idx + 1, (rem + 1) % 10, dp, b);
    if (three != -1)
    {
        if (twice) res = max(res, ret + (three << 1));
        else res = max(res, ret + three);
    }
    if (two != -1)
    {
        if (twice) res = max(res, ret + (two << 1));
        else res = max(res, ret + two);
    }
    if (one[0] != -1)
    {
        if (twice) res = max(res, ret + (one[0] << 1));
        else res = max(res, ret + one[0]);
    }
    twice = (rem == 8 || rem == 9);
    ret = saiki(idx + 1, (rem + 2) % 10, dp, b);
    if (one[1] != -1)
    {
        if (twice) res = max(res, ret + (one[0] << 1) + one[1]);
        else res = max(res, ret + one[0] + one[1]);
    }
    if (one[0] != -1 && two != -1)
    {
        if (twice) res = max(res, ret + (max(one[0], two) << 1) + min(one[0], two));
        else res = max(res, ret + one[0] + two);
    }
    if (one[2] != -1)
    {
        twice = (rem >= 7 && rem < 10);
        ret = saiki(idx + 1, (rem + 3) % 10, dp, b);
        if (twice) res = max(res, ret + (one[0] << 1) + one[1] + one[2]);
        else res = max(res, ret + one[0] + one[1] + one[2]);
    }
    dp[idx][rem] = res;
    return res;
}

void solve(Tuple!(int, int)[][] b)
{
    auto n = cast(int)b.length;
    auto dp = new long[][](n + 1, 10);
    foreach (i; 0 .. n + 1) fill(dp[i], -1);
    auto ans = saiki(0, 0, dp, b);
    writeln(ans);
}

int main(string[] args)
{
    int n;
    while (readf("%d\n", &n) == 1)
    {
        auto b = new Tuple!(int, int)[][n];
        foreach (i; 0 .. n)
        {
            int k;
            readf("%d\n", &k);
            b[i] = new Tuple!(int, int)[k];
            foreach (j; 0 .. k) readf("%d %d\n", &b[i][j][0], &b[i][j][1]);
        }
        solve(b);
    }
    return 0;
}


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

void main() {
  readln;

  auto a = readln.chomp.split.map!(to!int);

  int max = a[0];
  int min = a[0];
  int maxInd = 0;
  int minInd = 0;

  foreach (int i, e; a.array) {
    if (max < e) {
      max = e;
      maxInd = i;
    }

    if (min >= e) {
      min = e;
      minInd = i;
    }
  }

  auto ans = maxInd + a.length - minInd - 1;
  if (minInd < maxInd) ans--;
  ans.writeln;
}

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

void main()
{
	int n = to!int(readln.strip);
	auto line = to!(int[])(readln.strip.split);

	int left = fold!max(line);
	int indLeft = line.countUntil(left);
	copy(line[0..indLeft].dup, line[1..indLeft+1]);
	line[0] = left;

	int right = fold!min(line);
	line.reverse;
	int indRight = line.countUntil(right);
	writeln(indLeft + indRight);
}

import std.stdio;
import std.uni;
import std.string;
import core.stdc.stdio;
import std.array;
import std.algorithm;
import std.string;
import std.math;

int main(string[] argv)
{
	int n;
	scanf("%d", &n);
	int[] nums;
	nums.length = n;
	foreach (int i; 0..n)
	{
		scanf("%d", &nums[i]);
	}
	int min = int.max;
	int p = 0;
	int totalmoves = 0;
	foreach (int i; 0..n)
	{
		if (nums[i] <= min)
		{
			min = nums[i];
			p = i;
		}
	}
	totalmoves = (n - p - 1);
	foreach (int i; p..(n-1))
	{
		nums[i] = nums[i+1];
	}
	nums[nums.length - 1] = min;
	int max = int.min;
	foreach (int i; 0..n)
	{
		if (nums[i] > max)
		{
			max = nums[i];
			p = i;
		}
	}
	totalmoves += p;
	printf("%d", totalmoves);
	return 0;
}


import std.stdio, std.conv, std.string;
import std.array, std.range, std.algorithm, std.container;
import std.math, std.random, std.bigint, std.datetime, std.format;
string read(){ static string[] ss; while(!ss.length) ss = readln.chomp.split; string res = ss[0]; ss.popFront; return res; }

int DEBUG_LEVEL = 0;
void print()(){ writeln(""); }
void print(T, A ...)(T t, lazy A a){ write(t), print(a); }
void print(int level, T, A ...)(T t, lazy A a){ if(level <= DEBUG_LEVEL) print(t, a); }

void main(string[] args){
	if(args.length > 1 && args[1] == "-debug"){
		if(args.length > 2 && args[2].isNumeric) DEBUG_LEVEL = args[2].to!int;
		else DEBUG_LEVEL = 1;
	}

	int n = read.to!int;
	int x = read.to!int;
	int y = read.to!int;

	bool[] us = readln.chomp.map!(x => x == '1').array;
	bool[] ys;
	foreach_reverse(u; us) ys ~= u;

	print!1("ys:", ys);

	int ans;
	foreach(int i; 0 .. x){
		if(i == y && ! ys[i]) print!1("*"), ans += 1;
		if(i != y && ys[i]) print!1("-"), ans += 1;
		print!1(ans);
	}

	ans.writeln;

}

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, core.stdc.string;

void main() {
    auto s = readln.split.map!(to!int);
    auto N = s[0];
    auto X = s[1];
    auto Y = s[2];
    auto S = readln.chomp;

    int ans = 0;

    foreach (i; 0..X) {
        if (i < Y) {
            ans += S[N-i-1] == '1' ;
        } else if (i == Y) {
            ans += S[N-i-1] == '0';
        } else {
            ans += S[N-i-1] == '1' ;
        }
    }

    ans.writeln;
}

import std.stdio : writef, readf, readln, writeln, writefln;
import std.array : array, split;
import std.algorithm;
import std.conv : to;
import std.range : iota, tee;
import std.algorithm.comparison;
import std.container.rbtree : RBT = RedBlackTree;
import std.string : strip;
import core.memory : GC;
import std.typecons : tuple;

alias Tree = RBT!int;

void main() {
  GC.disable();

  //

  int n, x, y;
  readf(" %s %s %s\n", n, x, y);
  auto s = readln().strip.dup;

  reverse(s);

  int tt = 0;
  if (s[y] == '0') tt++;
  tt += s[0 .. y].filter!"a!='0'".array.length;

  tt += s[y+1 .. x].filter!"a!='0'".array.length;

  writeln(tt);

  //

}

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

string FMT_F = "%.10f";

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; }
string RDR()() { return readln.chomp; }
T[] ARR(T = long)(in string str, T fix = 0) { auto r = str.split.to!(T[]); r[] += fix; return r; }
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; }

bool inside(T)(T x, T b, T e) { return x >= b && x < e; }
long lcm(long x, long y) { return x * y / gcd(x, y); }

long mod = 10^^9 + 7;
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 main()
{
	auto N = RD!int;
	auto X = RD!int;
	auto Y = RD!int;
	auto s = RD!string;

	long ans;
	foreach_reverse (i; 0..N)
	{
		if (N-1-i == X) break;
		auto bit = N-1-i == Y ? '1' : '0';
		if (s[i] != bit)
			++ans;
	}

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