After too much playing on paper, Iahub has switched to computer games. The game he plays is called "Block Towers". It is played in a rectangular grid with n rows and m columns (it contains n × m cells). The goal of the game is to build your own city. Some cells in the grid are big holes, where Iahub can't build any building. The rest of cells are empty. In some empty cell Iahub can build exactly one tower of two following types:  Blue towers. Each has population limit equal to 100.  Red towers. Each has population limit equal to 200. However, it can be built in some cell only if in that moment at least one of the neighbouring cells has a Blue Tower. Two cells are neighbours is they share a side. Iahub is also allowed to destroy a building from any cell. He can do this operation as much as he wants. After destroying a building, the other buildings are not influenced, and the destroyed cell becomes empty (so Iahub can build a tower in this cell if needed, see the second example for such a case).Iahub can convince as many population as he wants to come into his city. So he needs to configure his city to allow maximum population possible. Therefore he should find a sequence of operations that builds the city in an optimal way, so that total population limit is as large as possible.He says he's the best at this game, but he doesn't have the optimal solution. Write a program that calculates the optimal one, to show him that he's not as good as he thinks.

The first line of the input contains two integers n and m (1 ≤ n, m ≤ 500). Each of the next n lines contains m characters, describing the grid. The j-th character in the i-th line is '.' if you're allowed to build at the cell with coordinates (i, j) a tower (empty cell) or '#' if there is a big hole there.

Print an integer k in the first line (0 ≤ k ≤ 106) — the number of operations Iahub should perform to obtain optimal result. Each of the following k lines must contain a single operation in the following format:   «B x y» (1 ≤ x ≤ n, 1 ≤ y ≤ m) — building a blue tower at the cell (x, y);  «R x y» (1 ≤ x ≤ n, 1 ≤ y ≤ m) — building a red tower at the cell (x, y);  «D x y» (1 ≤ x ≤ n, 1 ≤ y ≤ m) — destroying a tower at the cell (x, y).  If there are multiple solutions you can output any of them. Note, that you shouldn't minimize the number of operations.

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 core.memory;

struct StaticQueue(T, size_t maxSize)
{
  T[maxSize] data;
  size_t _front = 0;
  size_t _pastBack = 0;
  void clear()
  {
    _front = _pastBack;
  }
  bool empty()
  {
    return _front == _pastBack;
  }
  void removeFront()
  {
    _front++;
    if (_front == maxSize)
      _front = 0;
  }
  auto front()
  {
    return data[_front];
  }
  void insertBack(T t)
  {
    data[_pastBack] = t;
    _pastBack++;
    if (_pastBack == maxSize)
      _pastBack = 0;
  }
}

void main(string[] args)
{
  GC.disable;
  inputFile = stdin;
  debug inputFile = File(args[1]);
  enum deltas = [tuple(int(-1), int(0)), tuple(int(+1), int(0)),
                 tuple(int(0), int(-1)), tuple(int(0), int(+1))];
  auto n = next!int;
  auto m = next!int;
  auto cell = new string[](n);
  foreach(ref row; cell)
    row = next!string;
  auto visited = new bool[][](n, m);
  struct Op
  {
    string type;
    Tuple!(int, int) ind;
  }
  auto ops = new Op[](0);
  auto queue = StaticQueue!(Tuple!(int, int), 500 * 500)();
  foreach(i; 0 .. n)
    {
      foreach(j; 0 .. m)
        {
          if (!visited[i][j] && cell[i][j] == '.')
            {
              auto order = new Tuple!(int, int)[](0);
              queue.clear;
              queue.insertBack(tuple(i, j));
              visited[i][j] = true;
              while(!queue.empty)
                {
                  auto f = queue.front;
                  queue.removeFront;
                  order ~= f;
                  foreach(delta; deltas)
                    {
                      auto nei = tuple(f[0] + delta[0], f[1] + delta[1]);
                      if (nei[0] >= 0 && nei[0] < n && nei[1] >= 0 && nei[1] < m && !visited[nei[0]][nei[1]] && cell[nei[0]][nei[1]] == '.')
                        {
                          queue.insertBack(nei);
                          visited[nei[0]][nei[1]] = true;
                        }
                    }
                }
              foreach(node; order)
                {
                  ops ~= Op("B", node);
                }
              foreach_reverse(node; order[1 .. $])
                {
                  ops ~= Op("D", node);
                  ops ~= Op("R", node);
                }
            }
        }
    }
  ops.length.writeln;
  foreach(op; ops)
    {
      writeln(op.type, " ", op.ind[0] + 1, " ", op.ind[1] + 1);
    }
}
// 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 core.memory;

void main(string[] args)
{
  GC.disable;
  inputFile = stdin;
  debug inputFile = File(args[1]);
  enum deltas = [tuple(int(-1), int(0)), tuple(int(+1), int(0)),
                 tuple(int(0), int(-1)), tuple(int(0), int(+1))];
  auto n = next!int;
  auto m = next!int;
  auto cell = new string[](n);
  foreach(ref row; cell)
    row = next!string;
  auto visited = new bool[][](n, m);
  struct Op
  {
    string type;
    Tuple!(int, int) ind;
  }
  auto ops = new Op[](0);
  foreach(i; 0 .. n)
    {
      foreach(j; 0 .. m)
        {
          if (!visited[i][j] && cell[i][j] == '.')
            {
              auto order = new Tuple!(int, int)[](0);
              auto queue = DList!(Tuple!(int, int))(tuple!(int, int)(i, j));
              visited[i][j] = true;
              while(!queue.empty)
                {
                  auto f = queue.front;
                  queue.removeFront;
                  order ~= f;
                  foreach(delta; deltas)
                    {
                      auto nei = tuple(f[0] + delta[0], f[1] + delta[1]);
                      if (nei[0] >= 0 && nei[0] < n && nei[1] >= 0 && nei[1] < m && !visited[nei[0]][nei[1]] && cell[nei[0]][nei[1]] == '.')
                        {
                          queue.insertBack(nei);
                          visited[nei[0]][nei[1]] = true;
                        }
                    }
                }
              foreach(node; order)
                {
                  ops ~= Op("B", node);
                }
              foreach_reverse(node; order[1 .. $])
                {
                  ops ~= Op("D", node);
                  ops ~= Op("R", node);
                }
            }
        }
    }
  ops.length.writeln;
  foreach(op; ops)
    {
      writeln(op.type, " ", op.ind[0] + 1, " ", op.ind[1] + 1);
    }
}
// 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;

void main(string[] args)
{
  inputFile = stdin;
  debug inputFile = File(args[1]);
  enum deltas = [tuple(int(-1), int(0)), tuple(int(+1), int(0)),
                 tuple(int(0), int(-1)), tuple(int(0), int(+1))];
  auto n = next!int;
  auto m = next!int;
  auto cell = new string[](n);
  foreach(ref row; cell)
    row = next!string;
  auto visited = new bool[][](n, m);
  struct Op
  {
    string type;
    Tuple!(int, int) ind;
  }
  auto ops = new Op[](0);
  foreach(i; 0 .. n)
    {
      foreach(j; 0 .. m)
        {
          if (!visited[i][j] && cell[i][j] == '.')
            {
              auto order = new Tuple!(int, int)[](0);
              auto queue = DList!(Tuple!(int, int))(tuple!(int, int)(i, j));
              visited[i][j] = true;
              while(!queue.empty)
                {
                  auto f = queue.front;
                  queue.removeFront;
                  order ~= f;
                  foreach(delta; deltas)
                    {
                      auto nei = tuple(f[0] + delta[0], f[1] + delta[1]);
                      if (nei[0] >= 0 && nei[0] < n && nei[1] >= 0 && nei[1] < m && !visited[nei[0]][nei[1]] && cell[nei[0]][nei[1]] == '.')
                        {
                          queue.insertBack(nei);
                          visited[nei[0]][nei[1]] = true;
                        }
                    }
                }
              foreach(node; order)
                {
                  ops ~= Op("B", node);
                }
              foreach_reverse(node; order[1 .. $])
                {
                  ops ~= Op("D", node);
                  ops ~= Op("R", node);
                }
            }
        }
    }
  ops.length.writeln;
  foreach(op; ops)
    {
      writeln(op.type, " ", op.ind[0] + 1, " ", op.ind[1] + 1);
    }
}
// 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 core.memory;

struct StaticQueue(T, size_t maxSize)
{
  T[maxSize] data;
  size_t _front = 0;
  size_t _pastBack = 0;
  size_t len = 0;
  auto length()
  {
    return len;
  }
  void clear()
  {
    _front = _pastBack;
    len = 0;
  }
  bool empty()
  {
    return _front == _pastBack;
  }
  void removeFront()
  {
    _front++;
    if (_front == maxSize)
      _front = 0;
    len--;
  }
  auto front()
  {
    return data[_front];
  }
  void insertBack(T t)
  {
    data[_pastBack] = t;
    _pastBack++;
    if (_pastBack == maxSize)
      _pastBack = 0;
    len++;
  }
}

void main(string[] args)
{
  GC.disable;
  inputFile = stdin;
  debug inputFile = File(args[1]);
  enum deltas = [tuple(int(-1), int(0)), tuple(int(+1), int(0)),
                 tuple(int(0), int(-1)), tuple(int(0), int(+1))];
  auto n = next!int;
  auto m = next!int;
  auto cell = new string[](n);
  foreach(ref row; cell)
    row = next!string;
  auto visited = new bool[][](n, m);
  struct Op
  {
    string type;
    Tuple!(int, int) ind;
  }
  auto ops = StaticQueue!(Op, 500 * 500 * 3)();
  auto queue = StaticQueue!(Tuple!(int, int), 500 * 500)();
  foreach(i; 0 .. n)
    {
      foreach(j; 0 .. m)
        {
          if (!visited[i][j] && cell[i][j] == '.')
            {
              auto order = new Tuple!(int, int)[](0);
              queue.clear;
              queue.insertBack(tuple(i, j));
              visited[i][j] = true;
              while(!queue.empty)
                {
                  auto f = queue.front;
                  queue.removeFront;
                  order ~= f;
                  foreach(delta; deltas)
                    {
                      auto nei = tuple(f[0] + delta[0], f[1] + delta[1]);
                      if (nei[0] >= 0 && nei[0] < n && nei[1] >= 0 && nei[1] < m && !visited[nei[0]][nei[1]] && cell[nei[0]][nei[1]] == '.')
                        {
                          queue.insertBack(nei);
                          visited[nei[0]][nei[1]] = true;
                        }
                    }
                }
              foreach(node; order)
                {
                  ops.insertBack(Op("B", node));
                }
              foreach_reverse(node; order[1 .. $])
                {
                  ops.insertBack(Op("D", node));
                  ops.insertBack(Op("R", node));
                }
            }
        }
    }
  ops.length.writeln;
  while(!ops.empty)
    {
      auto op = ops.front;
      ops.removeFront;
      writeln(op.type, " ", op.ind[0] + 1, " ", op.ind[1] + 1);
    }
}
// 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;

void main(string[] args)
{
  inputFile = stdin;
  debug inputFile = File(args[1]);
  enum deltas = [tuple(int(-1), int(0)), tuple(int(+1), int(0)),
                 tuple(int(0), int(-1)), tuple(int(0), int(+1))];
  auto n = next!int;
  auto m = next!int;
  auto cell = new string[](n);
  foreach(ref row; cell)
    row = next!string;
  auto visited = new bool[][](n, m);
  foreach(i; 0 .. n)
    {
      foreach(j; 0 .. m)
        {
          if (!visited[i][j] && cell[i][j] == '.')
            {
              auto order = new Tuple!(int, int)[](0);
              auto queue = DList!(Tuple!(int, int))(tuple!(int, int)(i, j));
              visited[i][j] = true;
              while(!queue.empty)
                {
                  auto f = queue.front;
                  queue.removeFront;
                  order ~= f;
                  foreach(delta; deltas)
                    {
                      auto nei = tuple(f[0] + delta[0], f[1] + delta[1]);
                      if (nei[0] >= 0 && nei[0] < n && nei[1] >= 0 && nei[1] < m && !visited[nei[0]][nei[1]] && cell[nei[0]][nei[1]] == '.')
                        {
                          queue.insertBack(nei);
                          visited[nei[0]][nei[1]] = true;
                        }
                    }
                }
              foreach(node; order)
                {
                  writeln("B ", node[0] + 1, " ", node[1] + 1);
                }
              foreach_reverse(node; order[1 .. $])
                {
                  writeln("D ", node[0] + 1, " ", node[1] + 1);
                  writeln("R ", node[0] + 1, " ", node[1] + 1);
                }
            }
        }
    }
}

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


This is the easy version of the problem. The only difference between the two versions is the constraint on $$$n$$$. You can make hacks only if all versions of the problem are solved.A forest is an undirected graph without cycles (not necessarily connected).Mocha and Diana are friends in Zhijiang, both of them have a forest with nodes numbered from $$$1$$$ to $$$n$$$, and they would like to add edges to their forests such that:   After adding edges, both of their graphs are still forests.  They add the same edges. That is, if an edge $$$(u, v)$$$ is added to Mocha's forest, then an edge $$$(u, v)$$$ is added to Diana's forest, and vice versa. Mocha and Diana want to know the maximum number of edges they can add, and which edges to add.

The first line contains three integers $$$n$$$, $$$m_1$$$ and $$$m_2$$$ ($$$1 \le n \le 1000$$$, $$$0 \le m_1, m_2 < n$$$) — the number of nodes and the number of initial edges in Mocha's forest and Diana's forest. Each of the next $$$m_1$$$ lines contains two integers $$$u$$$ and $$$v$$$ ($$$1 \le u, v \le n$$$, $$$u \neq v$$$) — the edges in Mocha's forest. Each of the next $$$m_2$$$ lines contains two integers $$$u$$$ and $$$v$$$ ($$$1 \le u, v \le n$$$, $$$u \neq v$$$) — the edges in Diana's forest.

The first line contains only one integer $$$h$$$, the maximum number of edges Mocha and Diana can add (in each forest). Each of the next $$$h$$$ lines contains two integers $$$u$$$ and $$$v$$$ ($$$1 \le u, v \le n$$$, $$$u \neq v$$$) — the edge you add each time. If there are multiple correct answers, you can print any one of them.

NoteIn the first example, we cannot add any edge.In the second example, the initial forests are as follows.We can add an edge $$$(2, 4)$$$.

immutable multi = false;

struct US
{
	int[] parent;
	int[] sz;
	this(int n)
	{
		parent = new int[](n);
		foreach(i; 0 .. n) parent[i] = i;
		sz = new int[](n);
		sz[] = 1;
	}
	void unite(int u, int v)
	{
		debug writeln("uniting ", u, " ", v);
		u = rep(u);
		v = rep(v);
		if (sz[u] > sz[v]) swap(u, v);
		parent[u] = v;
		sz[v] += sz[u];
	}
	int rep(int v)
	{
		debug writeln("getting rep for ", v);
		if (parent[v] == v) return v;
		return parent[v] = rep(parent[v]);
	}
}

void solve(int tc)
{
	int n = readInt!int;
	auto u1 = US(n);
	auto u2 = US(n);
	auto m1 = readInt!int;
	auto m2 = readInt!int;
	foreach(i; 0 .. m1)
	{
		auto u = readInt!int - 1;
		auto v = readInt!int - 1;
		debug writeln(u, " -> ", v);
		u1.unite(u, v);
	}
	foreach(i; 0 .. m2)
	{
		auto u = readInt!int - 1;
		auto v = readInt!int - 1;
		u2.unite(u, v);
	}
	auto edges = new int[2][](0);
	foreach(i; 0 .. n)
	{
		foreach(j; 0 .. n)
		{
			if (u1.rep(i) != u1.rep(j) && u2.rep(i) != u2.rep(j))
			{
				u1.unite(i, j);
				u2.unite(i, j);
				edges ~= [i+1, j+1];
			}
		}
	}
	edges.length.writeln;
	foreach(e; edges) writeln(e[0], " ", e[1]);
}

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

struct UnionFind(T)
{
	void init(T n) { par = new T[](n); foreach (i; 0..n) par[i] = i; cnt = new T[](n); fill(cnt, 1); }
	T root(T i) { return par[i] == i ? i : (par[i] = root(par[i])); }
	bool same(T i, T j) { return root(i) == root(j); }
	void unite(T i, T j) { i = root(i); j = root(j); if (i == j) return; par[i] = j; cnt[j] += cnt[i]; }
	T size(T i) { return cnt[root(i)]; }
	T[] par, cnt;
}

void main()
{
	auto n = RD!int;
	auto m1 = RD!int;
	auto m2 = RD!int;

	UnionFind!int uf1, uf2;
	uf1.init(n);
	uf2.init(n);
	foreach (i; 0..m1)
	{
		auto u = RD!int-1;
		auto v = RD!int-1;
		uf1.unite(u, v);
	}
	foreach (i; 0..m2)
	{
		auto u = RD!int-1;
		auto v = RD!int-1;
		uf2.unite(u, v);
	}

	int[][] ans;
	foreach (i; 0..n)
	{
		foreach (j; i+1..n)
		{
			if (uf1.same(i, j) || uf2.same(i, j)) continue;
			uf1.unite(i, j);
			uf2.unite(i, j);
			ans ~= [i+1, j+1];
		}
	}

	writeln(ans.length);
	foreach (e; ans)
	{
		writeln(e[0], " ", e[1]);
	}
	stdout.flush;
	debug readln;
}


Let $$$F_k$$$ denote the $$$k$$$-th term of Fibonacci sequence, defined as below: $$$F_0 = F_1 = 1$$$ for any integer $$$n \geq 0$$$, $$$F_{n+2} = F_{n+1} + F_n$$$You are given a tree with $$$n$$$ vertices. Recall that a tree is a connected undirected graph without cycles.We call a tree a Fib-tree, if its number of vertices equals $$$F_k$$$ for some $$$k$$$, and at least one of the following conditions holds: The tree consists of only $$$1$$$ vertex; You can divide it into two Fib-trees by removing some edge of the tree. Determine whether the given tree is a Fib-tree or not.

The first line of the input contains a single integer $$$n$$$ ($$$1 \leq n \leq 2 \cdot 10^5$$$) — the number of vertices in the tree. Then $$$n-1$$$ lines follow, each of which contains two integers $$$u$$$ and $$$v$$$ ($$$1\leq u,v \leq n$$$, $$$u \neq v$$$), representing an edge between vertices $$$u$$$ and $$$v$$$. It's guaranteed that given edges form a tree.

Print "YES" if the given tree is a Fib-tree, or "NO" otherwise. You can print your answer in any case. For example, if the answer is "YES", then the output "Yes" or "yeS" will also be considered as correct answer.

NoteIn the first sample, we can cut the edge $$$(1, 2)$$$, and the tree will be split into $$$2$$$ trees of sizes $$$1$$$ and $$$2$$$ correspondently. Any tree of size $$$2$$$ is a Fib-tree, as it can be split into $$$2$$$ trees of size $$$1$$$.In the second sample, no matter what edge we cut, the tree will be split into $$$2$$$ trees of sizes $$$1$$$ and $$$4$$$. As $$$4$$$ isn't $$$F_k$$$ for any $$$k$$$, it's not Fib-tree.In the third sample, here is one possible order of cutting the edges so that all the trees in the process are Fib-trees: $$$(1, 3), (1, 2), (4, 5), (3, 4)$$$.

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 root(int[] uf, int u) {
  return (uf[u] < 0) ? u : (uf[u] = uf.root(uf[u]));
}
bool connect(int[] uf, int u, int v) {
  u = uf.root(u);
  v = uf.root(v);
  if (u == v) return false;
  if (uf[u] > uf[v]) swap(u, v);
  uf[u] += uf[v];
  uf[v] = u;
  return true;
}

int[] fib;

int N;
int[] A, B;

int[][] G;
bool[] del;
int[] sz, par, pari;
int[] us;

void dfs(int u, int p, int pi) {
  us ~= u;
  par[u] = p;
  pari[u] = pi;
  sz[u] = 1;
  foreach (i; G[u]) {
    if (!del[i]) {
      if (i != pi) {
        const v = A[i] ^ B[i] ^ u;
        dfs(v, u, i);
        sz[u] += sz[v];
      }
    }
  }
}

bool solve(int k, int rt) {
  debug {
    // writeln("solve ", k, " ", rt);
  }
  if (k <= 2) {
    return true;
  }
  us = [];
  dfs(rt, -1, -1);
  /*
  debug {
    writeln("solve ", k, " ", rt);
    writeln("  del = ", del);
    writeln("  us = ", us);
    writeln("  sz = ", sz);
    writeln("  par = ", par);
    writeln("  pari = ", pari);
  }
  //*/
  assert(sz[rt] == fib[k]);
  int[] vs, ps;
  foreach (u; us) {
    if (sz[u] == fib[k - 2] || fib[k] - sz[u] == fib[k - 2]) {
      vs ~= u;
      ps ~= par[u];
    }
  }
  foreach (v; vs) {
    del[pari[v]] = true;
  }
  if (vs.length == 0) {
    return false;
  } else if (vs.length == 1) {
    bool ret = true;
    if (sz[vs[0]] == fib[k - 2]) {
      ret = ret && solve(k - 2, vs[0]);
      ret = ret && solve(k - 1, ps[0]);
    } else {
      ret = ret && solve(k - 1, vs[0]);
      ret = ret && solve(k - 2, ps[0]);
    }
    return ret;
  } else if (vs.length == 2) {
    bool ret = true;
    if (sz[vs[0]] == fib[k - 2]) {
      if (sz[vs[1]] == fib[k - 2]) {
        ret = ret && solve(k - 2, vs[0]);
        ret = ret && solve(k - 2, vs[1]);
        ret = ret && solve(k - 3, ps[0]);
      } else {
        ret = ret && solve(k - 2, vs[0]);
        ret = ret && solve(k - 2, ps[1]);
        ret = ret && solve(k - 3, ps[0]);
      }
    } else {
      if (sz[vs[1]] == fib[k - 2]) {
        ret = ret && solve(k - 2, vs[1]);
        ret = ret && solve(k - 2, ps[0]);
        ret = ret && solve(k - 3, ps[1]);
      } else {
        assert(false);
      }
    }
    return ret;
  } else {
    assert(false);
  }
}

void main() {
  fib = new int[40];
  fib[0] = 1;
  fib[1] = 1;
  foreach (k; 2 .. fib.length) {
    fib[k] = fib[k - 1] + fib[k - 2];
  }
  debug {
    writeln("fib = ", fib);
  }

  try {
    for (; ; ) {
      N = readInt();
      A = new int[N - 1];
      B = new int[N - 1];
      foreach (i; 0 .. N - 1) {
        A[i] = readInt() - 1;
        B[i] = readInt() - 1;
      }
      debug {
        writeln("N = ", N);
        writeln("A = ", A);
        writeln("B = ", B);
      }

      G = new int[][N];
      foreach (i; 0 .. N - 1) {
        G[A[i]] ~= i;
        G[B[i]] ~= i;
      }
      del = new bool[N - 1];
      sz = new int[N];
      par = new int[N];
      pari = new int[N];

      bool ans = false;
      const k = fib.lowerBound(N);
      if (fib[k] == N) {
        ans = solve(k, 0);
      }
      writeln(ans ? "YES" : "NO");

      debug {
        auto brt = new bool[1 << N];
        foreach (p; 1 .. 1 << N) {
          if (!(p & p - 1)) {
            brt[p] = true;
          } else {
            auto uf = new int[N];
            uf[] = -1;
            foreach (i; 0 .. N - 1) {
              if ((p & 1 << A[i]) && (p & 1 << B[i])) {
                uf.connect(A[i], B[i]);
              }
            }
            int numComps;
            foreach (u; 0 .. N) {
              if (p & 1 << u) {
                if (uf[u] < 0) {
                  ++numComps;
                }
              }
            }
            if (fib.count(popcnt(p)) > 0 && numComps == 1) {
              for (int q = p; --q &= p; ) {
                if (brt[q] && brt[p ^ q]) {
                  brt[p] = true;
                  break;
                }
              }
            }
          }
        }
        assert(brt[$ - 1] == ans, format("%s %s %s: %s %s", N, A, B, brt[$ - 1], ans));
      }
    }
  } catch (EOFException e) {
  }
}

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 root(int[] uf, int u) {
  return (uf[u] < 0) ? u : (uf[u] = uf.root(uf[u]));
}
bool connect(int[] uf, int u, int v) {
  u = uf.root(u);
  v = uf.root(v);
  if (u == v) return false;
  if (uf[u] > uf[v]) swap(u, v);
  uf[u] += uf[v];
  uf[v] = u;
  return true;
}

int[] fib;

int N;
int[] A, B;

int[][] G;
bool[] del;
int[] sz, par, pari;
int[] us;

void dfs(int u, int p, int pi) {
  us ~= u;
  par[u] = p;
  pari[u] = pi;
  sz[u] = 1;
  foreach (i; G[u]) {
    if (!del[i]) {
      if (i != pi) {
        const v = A[i] ^ B[i] ^ u;
        dfs(v, u, i);
        sz[u] += sz[v];
      }
    }
  }
}

bool solve(int k, int rt) {
  if (k <= 2) {
    return true;
  }
  us = [];
  dfs(rt, -1, -1);
  /*
  debug {
    writeln("solve ", k, " ", rt);
    writeln("  us = ", us);
    writeln("  sz = ", sz);
    writeln("  par = ", par);
    writeln("  pari = ", pari);
  }
  //*/
  assert(sz[rt] == fib[k]);
  int[] vs;
  foreach (u; us) {
    if (sz[u] == fib[k - 2] || fib[k] - sz[u] == fib[k - 2]) {
      vs ~= u;
    }
  }
  foreach (v; vs) {
    del[pari[v]] = true;
  }
  if (vs.length == 0) {
    return false;
  } else if (vs.length == 1) {
    bool ret = true;
    if (sz[vs[0]] == fib[k - 2]) {
      ret = ret && solve(k - 2, vs[0]);
      ret = ret && solve(k - 1, par[vs[0]]);
    } else {
      ret = ret && solve(k - 1, vs[0]);
      ret = ret && solve(k - 2, par[vs[0]]);
    }
    return ret;
  } else if (vs.length == 2) {
    bool ret = true;
    if (sz[vs[0]] == fib[k - 2]) {
      if (sz[vs[1]] == fib[k - 2]) {
        ret = ret && solve(k - 2, vs[0]);
        ret = ret && solve(k - 2, vs[1]);
        ret = ret && solve(k - 3, par[vs[0]]);
      } else {
        ret = ret && solve(k - 2, vs[0]);
        ret = ret && solve(k - 2, par[vs[1]]);
        ret = ret && solve(k - 3, par[vs[0]]);
      }
    } else {
      if (sz[vs[1]] == fib[k - 2]) {
        ret = ret && solve(k - 2, vs[1]);
        ret = ret && solve(k - 2, par[vs[0]]);
        ret = ret && solve(k - 3, par[vs[1]]);
      } else {
        assert(false);
      }
    }
    return ret;
  } else {
    assert(false);
  }
}

void main() {
  fib = new int[40];
  fib[0] = 1;
  fib[1] = 1;
  foreach (k; 2 .. fib.length) {
    fib[k] = fib[k - 1] + fib[k - 2];
  }
  debug {
    writeln("fib = ", fib);
  }

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

      G = new int[][N];
      foreach (i; 0 .. N - 1) {
        G[A[i]] ~= i;
        G[B[i]] ~= i;
      }
      del = new bool[N - 1];
      sz = new int[N];
      par = new int[N];
      pari = new int[N];

      bool ans = false;
      const k = fib.lowerBound(N);
      if (fib[k] == N) {
        ans = solve(k, 0);
      }
      writeln(ans ? "YES" : "NO");

      debug {
        auto brt = new bool[1 << N];
        foreach (p; 1 .. 1 << N) {
          if (!(p & p - 1)) {
            brt[p] = true;
          } else {
            auto uf = new int[N];
            uf[] = -1;
            foreach (i; 0 .. N - 1) {
              if ((p & 1 << A[i]) && (p & 1 << B[i])) {
                uf.connect(A[i], B[i]);
              }
            }
            int numComps;
            foreach (u; 0 .. N) {
              if (p & 1 << u) {
                if (uf[u] < 0) {
                  ++numComps;
                }
              }
            }
            if (fib.count(popcnt(p)) > 0 && numComps == 1) {
              for (int q = p; --q &= p; ) {
                if (brt[q] && brt[p ^ q]) {
                  brt[p] = true;
                  break;
                }
              }
            }
          }
        }
        assert(brt[$ - 1] == ans, format("%s %s %s: %s %s", N, A, B, brt[$ - 1], ans));
      }
    }
  } catch (EOFException e) {
  }
}

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[] fib;

int N;
int[] A, B;

int[][] G;
bool[] del;
int[] sz, par, pari;
int[] us;

void dfs(int u, int p, int pi) {
  us ~= u;
  par[u] = p;
  pari[u] = pi;
  sz[u] += 1;
  foreach (i; G[u]) {
    if (!del[i]) {
      if (i != pi) {
        const v = A[i] ^ B[i] ^ u;
        dfs(v, u, i);
        sz[u] += sz[v];
      }
    }
  }
}

bool solve(int k, int rt) {
  if (k <= 2) {
    return true;
  }
  us = [];
  dfs(rt, -1, -1);
  assert(sz[rt] == fib[k]);
  int[] vs;
  foreach (v; us) {
    if (sz[v] == fib[k - 2] || sz[v] == fib[k - 1]) {
      vs ~= v;
    }
  }
  if (vs.length != 2) {
    return false;
  }
  foreach (v; vs) {
    del[pari[v]] = true;
  }
  bool ret = true;
  if (sz[vs[0]] == fib[k - 2]) {
    if (sz[vs[1]] == fib[k - 2]) {
      ret = ret && solve(k - 2, vs[0]);
      ret = ret && solve(k - 2, vs[1]);
      ret = ret && solve(k - 3, par[vs[0]]);
    } else {
      ret = ret && solve(k - 2, vs[0]);
      ret = ret && solve(k - 2, par[vs[1]]);
      ret = ret && solve(k - 3, par[vs[0]]);
    }
  } else {
    if (sz[vs[1]] == fib[k - 2]) {
      ret = ret && solve(k - 2, vs[1]);
      ret = ret && solve(k - 2, par[vs[0]]);
      ret = ret && solve(k - 3, par[vs[1]]);
    } else {
      assert(false);
    }
  }
  return ret;
}

void main() {
  fib = new int[40];
  fib[0] = 1;
  fib[1] = 1;
  foreach (k; 2 .. fib.length) {
    fib[k] = fib[k - 1] + fib[k - 2];
  }

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

      G = new int[][N];
      foreach (i; 0 .. N - 1) {
        G[A[i]] ~= i;
        G[B[i]] ~= i;
      }
      del = new bool[N - 1];
      sz = new int[N];
      par = new int[N];
      pari = new int[N];

      bool ans = false;
      const k = fib.lowerBound(N);
      if (fib[k] == N) {
        ans = solve(k, 0);
      }
      writeln(ans ? "YES" : "NO");
    }
  } catch (EOFException e) {
  }
}


You are given two non-empty strings $$$s$$$ and $$$t$$$, consisting of Latin letters.In one move, you can choose an occurrence of the string $$$t$$$ in the string $$$s$$$ and replace it with dots.Your task is to remove all occurrences of the string $$$t$$$ in the string $$$s$$$ in the minimum number of moves, and also calculate how many different sequences of moves of the minimum length exist.Two sequences of moves are considered different if the sets of indices at which the removed occurrences of the string $$$t$$$ in $$$s$$$ begin differ. For example, the sets $$$\{1, 2, 3\}$$$ and $$$\{1, 2, 4\}$$$ are considered different, the sets $$$\{2, 4, 6\}$$$ and $$$\{2, 6\}$$$ — too, but sets $$$\{3, 5\}$$$ and $$$\{5, 3\}$$$ — not.For example, let the string $$$s =$$$ "abababacababa" and the string $$$t =$$$ "aba". We can remove all occurrences of the string $$$t$$$ in $$$2$$$ moves by cutting out the occurrences of the string $$$t$$$ at the $$$3$$$th and $$$9$$$th positions. In this case, the string $$$s$$$ is an example of the form "ab...bac...ba". It is also possible to cut occurrences of the string $$$t$$$ at the $$$3$$$th and $$$11$$$th positions. There are two different sequences of minimum length moves.Since the answer can be large, output it modulo $$$10^9 + 7$$$.

The first line of the input contains a single integer $$$q$$$ ($$$1 \le q \le 50$$$) — the number of test cases. The descriptions of the sets follow. The first line of each set contains a non-empty string $$$s$$$ ($$$1 \le |s| \le 500$$$) consisting of lowercase Latin letters. The second line of each set contains a non-empty string $$$t$$$ ($$$1 \le |t| \le 500$$$) consisting of lowercase Latin letters. It is guaranteed that the sum of string lengths $$$s$$$ over all test cases does not exceed $$$500$$$. Similarly, it is guaranteed that the sum of string lengths $$$t$$$ over all test cases does not exceed $$$500$$$.

For each test case print two integers — the minimum number of moves and the number of different optimal sequences, modulo $$$10^9 + 7$$$.

8

abababacababa

aba

ddddddd

dddd

xyzxyz

xyz

abc

abcd

abacaba

abaca

abc

def

aaaaaaaa

a

aaaaaaaa

aa

NoteThe first test case is explained in the statement.In the second case, it is enough to cut any of the four occurrences.In the third case, string $$$s$$$ is the concatenation of two strings $$$t =$$$ "xyz", so there is a unique optimal sequence of $$$2$$$ moves.In the fourth and sixth cases, the string $$$s$$$ initially contains no occurrences of the string $$$t$$$.In the fifth case, the string $$$s$$$ contains exactly one occurrence of the string $$$t$$$.

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

enum long mod = cast(long)(1e9+7);

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

void solve() {
    auto S = read!string;
    auto T = read!string;
    int sn = S.length;
    int tn = T.length;
    int[] xs;
    for (int i = 0; i + tn <= sn; i++) {
        if (S[i .. (i + tn)] == T) {
            xs ~= i;
        }
    }

    const int INF = 1<<28;
    alias P = Tuple!(int, "m", long, "c");
    int N = xs.length;

    if (N == 0) {
        writeln("0 1");
        return;
    }

    int L = tn;
    auto f = new P[](N + 1);
    f[] = P(INF, -(1L<<56));
    f[0] = tuple(0, 1);
    for (int n = 0; n < N; n++) {
        int l;
        for (l = n; l < N && xs[l] - xs[n] < L; l++) {}
        for (int k = 0; k <= n; k++) {
            if (xs[n] - xs[k] < L) {
                if (f[l].m > f[k].m + 1) {
                    f[l].m = f[k].m + 1;
                    f[l].c = f[k].c;
                } else if (f[l].m == f[k].m + 1) {
                    f[l].c += f[k].c;
                    f[l].c %= mod;
                }
            }
        }
    }
    writefln("%s %s", f[N].m, f[N].c);
    /*
    writeln(S);
    writeln(T);
    writeln(xs);
    */
}


Andrew loves the sea. That's why, at the height of the summer season, he decided to go to the beach, taking a sunbed with him to sunbathe.The beach is a rectangular field with $$$n$$$ rows and $$$m$$$ columns. Some cells of the beach are free, some have roads, stones, shops and other non-movable objects. Some of two adjacent along the side cells can have sunbeds located either horizontally or vertically.Andrew hopes to put his sunbed somewhere, but that's a bad luck, there may no longer be free places for him! That's why Andrew asked you to help him to find a free place for his sunbed. Andrew's sunbed also should be places on two adjacent cells. If there are no two adjacent free cells, then in order to free some place for a sunbed, you will have to disturb other tourists. You can do the following actions:  Come to some sunbed and, after causing $$$p$$$ units of discomfort to its owner, lift the sunbed by one of its sides and rotate it by $$$90$$$ degrees. One half of the sunbed must remain in the same cell and another half of the sunbed must move to the free cell. At the same time, anything could be on the way of a sunbed during the rotation .   Rotation of the sunbed by $$$90$$$ degrees around cell $$$(1, 2)$$$.  Come to some sunbed and, after causing $$$q$$$ units of discomfort to its owner, shift the sunbed along its long side by one cell. One half of the sunbed must move to the place of another, and another — to the free cell.   Shift of the sunbed by one cell to the right. In any moment each sunbed occupies two adjacent free cells. You cannot move more than one sunbed at a time.Help Andrew to free a space for his sunbed, causing the minimum possible number of units of discomfort to other tourists, or detect that it is impossible.

The first line contains two integers $$$n$$$ and $$$m$$$ ($$$1 \le n, m \le 300\,000$$$, $$$1 \le n \cdot m \le 300\,000$$$) — the number of rows and columns in rectangle. The second line contains two integers $$$p$$$ and $$$q$$$ ($$$1 \le p, q \le 10^9$$$) — the number of units of discomfort caused by rotation and shift of a sunbed, respectively. Each of the following $$$n$$$ lines contains $$$m$$$ characters, describing cells of the rectangle. Each lines consists of characters "L", "R", "D", "U", "." and "#", denoting the type of the cell. Characters "L", "R", "D" and "U" denote a half of a sunbed placed in the cell — left, right, bottom and top half, respectively. Character "." denotes a free cell and character "#" — a cell, occupied by some non-movable object.

Print one integer — the minimum possible number of units of discomfort, caused to other tourists, to free a space for a sunbed. If it is impossible to free a space for a sunbed, print $$$-1$$$.

NoteIn the first example we can shift upper sunbed to the left and lower sunbed — to the right. Andrew will be able to put his sunbed vertically in the middle of the beach. We well cause $$$2 + 2 = 4$$$ units of discomfort. It is easy to prove that it is an optimal answer.    Optimal strategy in the first example (Andrew's sunbed is colored white).  In the second example it is impossible to free a space for Andrew's sunbed. All possible states of the beach after any rotates and shifts are illustrated in the problem statement.

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

immutable int dirs = 4;
immutable int  [dirs] dRow  = [ -1,   0,  +1,   0];
immutable int  [dirs] dCol  = [  0,  -1,   0,  +1];
immutable char [dirs] dName = ['U', 'L', 'D', 'R'];
immutable long infinity = long.max / 8;
immutable int NA = -1;
alias Coord = Tuple !(int, q{row}, int, q{col});
alias Record = Tuple !(long, q{dist}, int, q{row}, int, q{col});

long solve (int rows, int cols, string [] board, int p, int q)
{
	auto d = new long [] [] (rows, cols);

	auto t = redBlackTree !(Record);
	foreach (row; 0..rows)
	{
		foreach (col; 0..cols)
		{
			d[row][col] = (board[row][col] == '.' ? 0 : infinity);
			if (d[row][col] == 0)
			{
				t.insert (Record (0, row, col));
			}
		}
	}

	while (!t.empty)
	{
		auto cur = t.front;
		t.removeFront ();
		foreach (dir; 0..dirs)
		{
			auto nRow = cur.row + dRow[dir];
			auto nCol = cur.col + dCol[dir];
			if (nRow < 0 || rows <= nRow ||
			    nCol < 0 || cols <= nCol)
			{
				continue;
			}
			auto delta = dName[].countUntil (board[nRow][nCol]);
			if (delta == NA)
			{
				continue;
			}
			delta ^= 2;
			auto pRow = nRow + dRow[delta];
			auto pCol = nCol + dCol[delta];
			auto cost = (dir == delta) ? q : p;
			if (d[pRow][pCol] > cur.dist + cost)
			{
				t.removeKey (Record (d[pRow][pCol], pRow, pCol));
				d[pRow][pCol] = cur.dist + cost;
				t.insert (Record (d[pRow][pCol], pRow, pCol));
			}
		}
	}

	long res = infinity;
	foreach (row; 0..rows)
	{
		foreach (col; 0..cols)
		{
			if (row + 1 < rows)
			{
				res = min (res, d[row][col] + d[row + 1][col]);
			}
			if (col + 1 < cols)
			{
				res = min (res, d[row][col] + d[row][col + 1]);
			}
		}
	}
	return (res == infinity) ? NA : res;
}

void main ()
{
	int rows, cols;
	while (readf !(" %s %s") (rows, cols) > 0)
	{
		int p, q;
		readf !(" %s %s") (p, q);
		readln;
		string [] board;
		foreach (row; 0..rows)
		{
			board ~= readln.strip;
		}
		writeln (solve (rows, cols, board, p, q));
	}
}


Polycarp has guessed three positive integers $$$a$$$, $$$b$$$ and $$$c$$$. He keeps these numbers in secret, but he writes down four numbers on a board in arbitrary order — their pairwise sums (three numbers) and sum of all three numbers (one number). So, there are four numbers on a board in random order: $$$a+b$$$, $$$a+c$$$, $$$b+c$$$ and $$$a+b+c$$$.You have to guess three numbers $$$a$$$, $$$b$$$ and $$$c$$$ using given numbers. Print three guessed integers in any order.Pay attention that some given numbers $$$a$$$, $$$b$$$ and $$$c$$$ can be equal (it is also possible that $$$a=b=c$$$).

The only line of the input contains four positive integers $$$x_1, x_2, x_3, x_4$$$ ($$$2 \le x_i \le 10^9$$$) — numbers written on a board in random order. It is guaranteed that the answer exists for the given number $$$x_1, x_2, x_3, x_4$$$.

Print such positive integers $$$a$$$, $$$b$$$ and $$$c$$$ that four numbers written on a board are values $$$a+b$$$, $$$a+c$$$, $$$b+c$$$ and $$$a+b+c$$$ written in some order. Print $$$a$$$, $$$b$$$ and $$$c$$$ in any order. If there are several answers, you can print any. It is guaranteed that the answer exists.

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

void main()
{
    int[] input = readln().split.map!"a.to!int".array;
    input = input.sort.reverse.array;
    int a = input[0] - input[1];
    int b = input[0] - input[2];
    int c = input[0] - input[3];
    writeln(a, " ", b, " ", c);
}

// Vicfred
// https://codeforces.com/problemset/problem/1154/A
import std.algorithm;
import std.array;
import std.conv;
import std.stdio;

void main() {
    int[] numbers = readln.split.map!(to!int).array;
    numbers.sort;
    int abc = numbers[$-1];
    int x = abc-numbers[0];
    writefln("%d %d %d", x, numbers[1]-x, numbers[2]-x);
}

import std.stdio;
import std.math;
import std.algorithm;
import std.array;
import std.string;
import std.conv;
import std.range;
import std.file;
import std.datetime;

void main() {

	int[] sayılar = stdin.readln.strip.split.map!(a=> a.to!int()).array;
	int toplam = sayılar.maxElement();
	sayılar = sayılar.remove( sayılar.countUntil(toplam) ).array;
	int bArtıC = sayılar.maxElement();
	int a = toplam - bArtıC;
	sayılar = sayılar.remove( sayılar.countUntil(bArtıC) ).array;

	int aArtıC = sayılar.maxElement();
	int c = aArtıC - a;
	int b = toplam - aArtıC;

	writeln(a, " ", b, " ", c);

	//writeln();

}

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

const long mod = 1_000_000_007;

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[] xs = readln.chomp.split.map!(to!int).array;

	int s = -1;
	foreach(x; xs) s = max(s, x);

	int[] as;
	foreach(x; xs) if(x < s) as ~= s - x;

	as.map!(to!string).array.join(" ").writeln;

}
/*

The largest must be a + b + c.
Call it s.

Others are s - a, s - b, s - c.

*/

import std.stdio;

int main()
{
	int n(int a, int b)
	{
		if (a>=b)
		{
			return a;
		}
		else
		{
			return b;
		}
	}
	int m(int a, int b, int c, int d)
	{
		return n(n(a,b),n(c,d));
	}
	int a=0;
	int b=0;
	int c=0;
	int d=0;
	readf(" %d", &a);
	readf(" %d", &b);
	readf(" %d", &c);
	readf(" %d", &d);
	int e=m(a,b,c,d);
	if (e==a)
	{
		writeln(e-b);
		writeln(e-c);
		writeln(e-d);
	}
	else if (e==b)
	{
		writeln(e-a);
		writeln(e-c);
		writeln(e-d);
	}
	else if (e==c)
	{
		writeln(e-a);
		writeln(e-b);
		writeln(e-d);
	}
	else
	{
		writeln(e-a);
		writeln(e-b);
		writeln(e-c);
	}
	return 0;
}

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; }
bool minimize(T)(ref T x, T y) { if (x > y) { x = y; return true; } else { return false; } }
bool maximize(T)(ref T x, T y) { if (x < y) { x = y; return true; } else { return false; } }

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 x = new long[](4);
	foreach (i; 0..4)
	{
		x[i] = RD;
	}
	x.sort();

	writeln(x[3] - x[0], " ", x[3] - x[1], " ", x[3] -x[2]);
	stdout.flush();
	debug readln();
}


You are given a binary array $$$a$$$ (all elements of the array are $$$0$$$ or $$$1$$$) of length $$$n$$$. You wish to sort this array, but unfortunately, your algorithms teacher forgot to teach you sorting algorithms. You perform the following operations until $$$a$$$ is sorted:  Choose two random indices $$$i$$$ and $$$j$$$ such that $$$i < j$$$. Indices are chosen equally probable among all pairs of indices $$$(i, j)$$$ such that $$$1 \le i < j \le n$$$.  If $$$a_i > a_j$$$, then swap elements $$$a_i$$$ and $$$a_j$$$. What is the expected number of such operations you will perform before the array becomes sorted?It can be shown that the answer can be expressed as an irreducible fraction $$$\frac{p}{q}$$$, where $$$p$$$ and $$$q$$$ are integers and $$$q \not \equiv 0 \pmod{998\,244\,353}$$$. Output the integer equal to $$$p \cdot q^{-1} \bmod 998\,244\,353$$$. In other words, output such an integer $$$x$$$ that $$$0 \le x < 998\,244\,353$$$ and $$$x \cdot q \equiv p \pmod{998\,244\,353}$$$.

Each test contains multiple test cases. The first line contains the number of test cases $$$t$$$ ($$$1 \le t \le 10^5$$$). Description of the test cases follows. The first line of each test case contains an integer $$$n$$$ ($$$1 \le n \le 200\,000$$$) — the number of elements in the binary array. The second line of each test case contains $$$n$$$ integers $$$a_1, a_2, \ldots, a_n$$$ ($$$a_i \in \{0, 1\}$$$) — elements of the array. It's guaranteed that sum of $$$n$$$ over all test cases does not exceed $$$200\,000$$$.

For each test case print one integer — the value $$$p \cdot q^{-1} \bmod 998\,244\,353$$$.

NoteConsider the first test case. If the pair of indices $$$(2, 3)$$$ will be chosen, these elements will be swapped and array will become sorted. Otherwise, if one of pairs $$$(1, 2)$$$ or $$$(1, 3)$$$ will be selected, nothing will happen. So, the probability that the array will become sorted after one operation is $$$\frac{1}{3}$$$, the probability that the array will become sorted after two operations is $$$\frac{2}{3} \cdot \frac{1}{3}$$$, the probability that the array will become sorted after three operations is $$$\frac{2}{3} \cdot \frac{2}{3} \cdot \frac{1}{3}$$$ and so on. The expected number of operations is $$$\sum \limits_{i=1}^{\infty} \left(\frac{2}{3} \right)^{i - 1} \cdot \frac{1}{3} \cdot i = 3$$$.In the second test case the array is already sorted so the expected number of operations is zero.In the third test case the expected number of operations equals to $$$\frac{75}{4}$$$ so the answer is $$$75 \cdot 4^{-1} \equiv 249\,561\,107 \pmod {998\,244\,353}$$$.

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

immutable long mod = 998_244_353;

long powMod (long a, long p)
{
	long res = 1;
	for ( ; p > 0; p >>= 1)
	{
		if (p & 1)
		{
			res = (res * 1L * a) % mod;
		}
		a = (a * 1L * a) % mod;
	}
	return res;
}

long invMod (long a)
{
	return powMod (a, mod - 2);
}

void main ()
{
	auto tests = readln.strip.to !(int);
	foreach (test; 0..tests)
	{
		auto n = readln.strip.to !(int);
		auto a = readln.splitter.map !(to !(long)).array;

		long invs = 0;
		int i = 0;
		int j = n - 1;
		while (true)
		{
			while (i < n && a[i] == 0)
			{
				i += 1;
			}
			while (j >= 0 && a[j] == 1)
			{
				j -= 1;
			}
			if (i >= j)
			{
				break;
			}
			invs += 1;
			i += 1;
			j -= 1;
		}

		auto cn2 = n;
		cn2 = (cn2 * 1L * (n - 1)) % mod;
		cn2 = (cn2 * 1L * invMod (2)) % mod;

		long res = 0;
		foreach (k; 0..invs)
		{
			auto cur = k + 1;
			cur = (cur * 1L * (k + 1)) % mod;
			res = (res + cn2 * 1L * invMod (cur)) % mod;
		}
		writeln (res);
	}
}

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 = read!int;
    auto A = readarray!int;

    int nz = A.count!(a => a == 0);
    int t0 = A[0 .. nz].count!(a => a == 1);
    //writeln([nz, t0]);

    MInt p(int t) {
        long t2 = cast(long)(t) * t;
        long nC2 = cast(long)(N) * (N - 1) / 2;
        return MInt(t2) / nC2;
    }

    auto E = new MInt[t0 + 1];
    E[0] = 0;
    for (int t = 0; t < t0; t++) {
        E[t+1] = E[t] + 1 / p(t+1);
    }
    //writeln(E);
    writeln(E[t0]);
}

alias MInt = ModInt!998244353L;

struct ModInt(long mod) {
    invariant() {
        assert(0 <= val && val < mod);
    }
    long val;
    this(long v) { this.val = (mod * mod + v) % mod; }
    ModInt opBinary(string op : "+")(int y) const { return ModInt(this.val + y); }
    ModInt opBinary(string op : "-")(int y) const { return ModInt(this.val - y); }
    ModInt opBinary(string op : "*")(int y) const { return ModInt(this.val * y); }
    ModInt opBinary(string op : "/")(int y) const { return ModInt(this.val * inv(y)); }
    ModInt opBinary(string op : "+")(long y) const { return ModInt(this.val + y); }
    ModInt opBinary(string op : "-")(long y) const { return ModInt(this.val - y); }
    ModInt opBinary(string op : "*")(long y) const { return ModInt(this.val * y); }
    ModInt opBinary(string op : "/")(long y) const { return ModInt(this.val * inv(y)); }
    ModInt opBinary(string op : "+")(ModInt y) const { return ModInt(this.val + y.val); }
    ModInt opBinary(string op : "-")(ModInt y) const { return ModInt(this.val - y.val); }
    ModInt opBinary(string op : "*")(ModInt y) const { return ModInt(this.val * y.val); }
    ModInt opBinary(string op : "/")(ModInt y) const { return ModInt(this.val * inv(y.val)); }
    ModInt opBinaryRight(string op : "+")(int y) const { return ModInt(this.val + y); }
    ModInt opBinaryRight(string op : "-")(int y) const { return ModInt(y - this.val); }
    ModInt opBinaryRight(string op : "*")(int y) const { return ModInt(this.val * y); }
    ModInt opBinaryRight(string op : "/")(int y) const { return ModInt(inv(this.val) * y); }
    ModInt opBinaryRight(string op : "+")(long y) const { return ModInt(this.val + y); }
    ModInt opBinaryRight(string op : "-")(long y) const { return ModInt(y - this.val); }
    ModInt opBinaryRight(string op : "*")(long y) const { return ModInt(this.val * y); }
    ModInt opBinaryRight(string op : "/")(long y) const { return ModInt(inv(this.val) * y); }
    void opAssign(int y) { this.val = y; }
    void opAssign(long y) { this.val = y; }
    void opOpAssign(string op : "+")(int y) { this.val = (this.val + mod * mod + y) % mod; }
    void opOpAssign(string op : "-")(int y) { this.val = (this.val + mod * mod - y) % mod; }
    void opOpAssign(string op : "*")(int y) { this.val = (this.val * y) % mod; }
    void opOpAssign(string op : "/")(int y) { this.val = (this.val * inv(y)) % mod; }
    void opOpAssign(string op : "+")(long y) { this.val = (this.val + mod * mod + y) % mod; }
    void opOpAssign(string op : "-")(long y) { this.val = (this.val + mod * mod - y) % mod; }
    void opOpAssign(string op : "*")(long y) { this.val = (this.val * y) % mod; }
    void opOpAssign(string op : "/")(long y) { this.val = (this.val * inv(y)) % mod; }
    void opOpAssign(string op : "+")(ModInt y) { this.val = (this.val + mod * mod + y.val) % mod; }
    void opOpAssign(string op : "-")(ModInt y) { this.val = (this.val + mod * mod - y.val) % mod; }
    void opOpAssign(string op : "*")(ModInt y) { this.val = (this.val * y.val) % mod; }
    void opOpAssign(string op : "/")(ModInt y) { this.val = (this.val * inv(y.val)) % mod; }
    ModInt opUnary(string op : "-")() const { return ModInt(mod - this.val); }
    string toString() const { return val.to!string; }
    ModInt pow(long n) { return ModInt(pow(this.val, n, mod)); }
    ModInt pow(ModInt n) { return ModInt(pow(this.val, n.val, mod)); }
    static long pow(long x, long n, long mod) {
        if (n == 0) return 1L;
        x %= mod;
        if (n == 1) return x;
        if (n % 2 == 0) {
            long y = pow(x, n/2, mod);
            return y * y % mod;
        } else {
            return x * pow(x, n-1, mod) % mod;
        }
    }
    static long extgcd(long a, long b, ref long x, ref long y) {
        if (b == 0) {
            x = 1;
            y = 0;
            return a;
        }
        long d = extgcd(b, a % b, y, x);
        y -= a / b * x;
        return d;
    }
    static long inv(long a) {
        long x, y;
        extgcd(a, mod, x, y);
        return (x % mod + mod) % mod;
    }
}

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

struct ModInt(uint M_) {
  import std.conv : to;
  alias M = M_;
  uint x;
  this(ModInt a) { x = a.x; }
  this(uint x_) { x = x_ % M; }
  this(ulong x_) { x = cast(uint)(x_ % M); }
  this(int x_) { x = ((x_ %= cast(int)(M)) < 0) ? (x_ + cast(int)(M)) : x_; }
  this(long x_) { x = cast(uint)(((x_ %= cast(long)(M)) < 0) ? (x_ + cast(long)(M)) : x_); }
  ref ModInt opAssign(T)(inout(T) a) if (is(T == uint) || is(T == ulong) || is(T == int) || is(T == long)) { return this = ModInt(a); }
  ref ModInt opOpAssign(string op, T)(T a) {
    static if (is(T == ModInt)) {
      static if (op == "+") { x = ((x += a.x) >= M) ? (x - M) : x; }
      else static if (op == "-") { x = ((x -= a.x) >= M) ? (x + M) : x; }
      else static if (op == "*") { x = cast(uint)((cast(ulong)(x) * a.x) % M); }
      else static if (op == "/") { this *= a.inv(); }
      else static assert(false);
      return this;
    } else static if (op == "^^") {
      if (a < 0) return this = inv()^^(-a);
      ModInt b = this, c = 1U;
      for (long e = a; e; e >>= 1) { if (e & 1) c *= b; b *= b; }
      return this = c;
    } else {
      return mixin("this " ~ op ~ "= ModInt(a)");
    }
  }
  ModInt inv() const {
    uint a = M, b = x; int y = 0, z = 1;
    for (; b; ) { const q = a / b; const c = a - q * b; a = b; b = c; const w = y - cast(int)(q) * z; y = z; z = w; }
    assert(a == 1); return ModInt(y);
  }
  ModInt opUnary(string op)() const {
    static if (op == "+") { return this; }
    else static if (op == "-") { ModInt a; a.x = x ? (M - x) : 0U; return a; }
    else static assert(false);
  }
  ModInt opBinary(string op, T)(T a) const { return mixin("ModInt(this) " ~ op ~ "= a"); }
  ModInt opBinaryRight(string op, T)(T a) const { return mixin("ModInt(a) " ~ op ~ "= this"); }
  bool opCast(T: bool)() const { return (x != 0U); }
  string toString() const { return x.to!string; }
}

enum MO = 998244353;
alias Mint = ModInt!MO;

enum LIM_INV = 400_010;
Mint[] inv, fac, invFac;
void prepare() {
  inv = new Mint[LIM_INV];
  fac = new Mint[LIM_INV];
  invFac = new Mint[LIM_INV];
  inv[1] = 1;
  foreach (i; 2 .. LIM_INV) {
    inv[i] = -((Mint.M / i) * inv[cast(size_t)(Mint.M % i)]);
  }
  fac[0] = invFac[0] = 1;
  foreach (i; 1 .. LIM_INV) {
    fac[i] = fac[i - 1] * i;
    invFac[i] = invFac[i - 1] * inv[i];
  }
}
Mint binom(long n, long k) {
  if (n < 0) {
    if (k >= 0) {
      return (-1)^^(k & 1) * binom(-n + k - 1, k);
    } else if (n - k >= 0) {
      return (-1)^^((n - k) & 1) * binom(-k - 1, n - k);
    } else {
      return Mint(0);
    }
  } else {
    if (0 <= k && k <= n) {
      assert(n < LIM_INV);
      return fac[cast(size_t)(n)] * invFac[cast(size_t)(k)] * invFac[cast(size_t)(n - k)];
    } else {
      return Mint(0);
    }
  }
}

void main() {
  prepare;

  try {
    for (; ; ) {
      const numCases = readInt;
      foreach (caseId; 0 .. numCases) {
        const N = readInt;
        auto A = new int[N];
        foreach (i; 0 .. N) {
          A[i] = readInt;
        }

        const K = A.sum;
        const L = min(K, N - K);

        const Mint all = 1L * N * (N - 1) / 2;
        auto dp = new Mint[L + 2];
        foreach (a; 1 .. L + 1) {
          dp[a] = all * inv[a] * inv[a] + dp[a - 1];
        }

        const S = A[0 .. N - K].sum;
        writeln(dp[S]);
      }
    }
  } catch (EOFException e) {
  }
}

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

immutable int mod = 998_244_353;

int powMod (int a, int p)
{
	int res = 1;
	for ( ; p > 0; p >>= 1)
	{
		if (p & 1)
		{
			res = (res * 1L * a) % mod;
		}
		a = (a * 1L * a) % mod;
	}
	return res;
}

int invMod (int a)
{
	return powMod (a, mod - 2);
}

void main ()
{
	auto tests = readln.strip.to !(int);
	foreach (test; 0..tests)
	{
		auto n = readln.strip.to !(int);
		auto a = readln.splitter.map !(to !(int)).array;

		int invs = 0;
		int i = 0;
		int j = n - 1;
		while (true)
		{
			while (i < n && a[i] == 0)
			{
				i += 1;
			}
			while (j >= 0 && a[j] == 1)
			{
				j -= 1;
			}
			if (i >= j)
			{
				break;
			}
			invs += 1;
			i += 1;
			j -= 1;
		}

		auto cn2 = n;
		cn2 = (cn2 * 1L * (n - 1)) % mod;
		cn2 = (cn2 * 1L * invMod (2)) % mod;

		int res = 0;
		foreach (k; 0..invs)
		{
			auto cur = k + 1;
			cur = (cur * 1L * (k + 1)) % mod;
			res = (res + cn2 * 1L * invMod (cur)) % mod;
		}
		writeln (res);
	}
}


Alice's potion making professor gave the following assignment to his students: brew a potion using $$$n$$$ ingredients, such that the proportion of ingredient $$$i$$$ in the final potion is $$$r_i > 0$$$ (and $$$r_1 + r_2 + \cdots + r_n = 1$$$).He forgot the recipe, and now all he remembers is a set of $$$n-1$$$ facts of the form, "ingredients $$$i$$$ and $$$j$$$ should have a ratio of $$$x$$$ to $$$y$$$" (i.e., if $$$a_i$$$ and $$$a_j$$$ are the amounts of ingredient $$$i$$$ and $$$j$$$ in the potion respectively, then it must hold $$$a_i/a_j = x/y$$$), where $$$x$$$ and $$$y$$$ are positive integers. However, it is guaranteed that the set of facts he remembers is sufficient to uniquely determine the original values $$$r_i$$$.He decided that he will allow the students to pass the class as long as they submit a potion which satisfies all of the $$$n-1$$$ requirements (there may be many such satisfactory potions), and contains a positive integer amount of each ingredient.Find the minimum total amount of ingredients needed to make a potion which passes the class. As the result can be very large, you should print the answer modulo $$$998\,244\,353$$$.

The first line contains a single integer $$$t$$$ ($$$1 \le t \le 10^4$$$) — the number of test cases. The first line of each test case contains a single integer $$$n$$$ ($$$2 \le n \le 2 \cdot 10^5$$$). Each of the next $$$n-1$$$ lines contains four integers $$$i, j, x, y$$$ ($$$1 \le i, j \le n$$$, $$$i\not=j$$$, $$$1\le x, y \le n$$$) — ingredients $$$i$$$ and $$$j$$$ should have a ratio of $$$x$$$ to $$$y$$$. It is guaranteed that the set of facts is sufficient to uniquely determine the original values $$$r_i$$$. It is also guaranteed that the sum of $$$n$$$ for all test cases does not exceed $$$2 \cdot 10^5$$$.

For each test case, print the minimum total amount of ingredients needed to make a potion which passes the class, modulo $$$998\,244\,353$$$.

NoteIn the first test case, the minimum total amount of ingredients is $$$69$$$. In fact, the amounts of ingredients $$$1, 2, 3, 4$$$ of a valid potion are $$$16, 12, 9, 32$$$, respectively. The potion is valid because   Ingredients $$$3$$$ and $$$2$$$ have a ratio of $$$9 : 12 = 3 : 4$$$;  Ingredients $$$1$$$ and $$$2$$$ have a ratio of $$$16 : 12 = 4 : 3$$$;  Ingredients $$$1$$$ and $$$4$$$ have a ratio of $$$16 : 32 = 2 : 4$$$. In the second test case, the amounts of ingredients $$$1, 2, 3, 4, 5, 6, 7, 8$$$ in the potion that minimizes the total amount of ingredients are $$$60, 60, 24, 48, 32, 60, 45, 30$$$.

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

immutable int mod   = 998_244_353;
immutable int limit =     200_005;

bool [] sieve;
int [] divs;
int [] primes;
int [] inv;

int powMod (int a, int p)
{
	int res = 1;
	for ( ; p > 0; p >>= 1)
	{
		if (p & 1)
		{
			res = (res * 1L * a) % mod;
		}
		a = (a * 1L * a) % mod;
	}
	return res;
}

alias invMod = a => powMod (a, mod - 2);

void prepare ()
{
	sieve = new bool [limit];
	sieve[] = true;
	sieve[0] = sieve[1] = false;

	for (int d = 2; d * d < limit; d++)
	{
		if (sieve[d])
		{
			for (int e = d; e * d < limit; e++)
			{
				sieve[e * d] = false;
			}
		}
	}

	divs = new int [limit];
	for (int d = 2; d < limit; d++)
	{
		if (sieve[d])
		{
			for (int e = 1; e * d < limit; e++)
			{
				if (divs[e * d] == 0)
				{
					divs[e * d] = d;
				}
			}
		}
	}

	primes = null;
	foreach (d; 0..limit)
	{
		if (sieve[d])
		{
			primes ~= d;
		}
	}

	inv = new int [limit];
	foreach (d; 1..limit)
	{
		inv[d] = invMod (d);
	}
}

void main ()
{
	prepare ();
	auto tests = readln.strip.to !(int);
	foreach (test; 0..tests)
	{
		auto n = readln.strip.to !(int);
		alias Edge = Tuple !(int, q{v}, int, q{x}, int, q{y});
		auto a = new Edge [] [n];
		foreach (r; 0..n - 1)
		{
			int i, j, x, y;
			readf !(" %s %s %s %s") (i, j, x, y);
			i -= 1;
			j -= 1;
			auto d = gcd (x, y);
			x /= d;
			y /= d;
			a[i] ~= Edge (j, x, y);
			a[j] ~= Edge (i, y, x);
		}
		readln;

		auto cp = new int [limit];
		int mult = 1;
		int total = 0;

		void recur (int u, int p, int cur)
		{
			debug {writeln (u, " ", cur);}
			total = (total + cur) % mod;
			foreach (e; a[u])
			{
				if (e.v == p)
				{
					continue;
				}
				debug {writeln ("to ", e);}
				int next = cur;
				for (int x = e.x; divs[x] != 0; x /= divs[x])
				{
					next = (next * 1L * inv[divs[x]]) % mod;
					if (cp[divs[x]] == 0)
					{
						debug {writeln (" * ", divs[x]);}
						mult = (mult * 1L * divs[x]) % mod;
					}
					else
					{
						cp[divs[x]] -= 1;
					}
				}
				for (int y = e.y; divs[y] != 0; y /= divs[y])
				{
					next = (next * 1L * divs[y]) % mod;
					cp[divs[y]] += 1;
				}
				recur (e.v, u, next);
				for (int x = e.x; divs[x] != 0; x /= divs[x])
				{
					cp[divs[x]] += 1;
				}
				for (int y = e.y; divs[y] != 0; y /= divs[y])
				{
					cp[divs[y]] -= 1;
				}
			}
		}

		recur (0, -1, 1);
		writeln ((total * 1L * mult) % mod);
	}
}

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

immutable int mod   = 998_244_353;
immutable int limit =     200_005;

bool [] sieve;
int [] divs;
int [] primes;
int [] inv;

int powMod (int a, int p)
{
	int res = 1;
	for ( ; p > 0; p >>= 1)
	{
		if (p & 1)
		{
			res = (res * 1L * a) % mod;
		}
		a = (a * 1L * a) % mod;
	}
	return res;
}

alias invMod = a => powMod (a, mod - 2);

void prepare ()
{
	sieve = new bool [limit];
	sieve[] = true;
	sieve[0] = sieve[1] = false;
	divs = new int [limit];

	for (int d = 2; d * d < limit; d++)
	{
		if (sieve[d])
		{
			for (int e = d; e * d < limit; e++)
			{
				sieve[e * d] = false;
			}
			for (int e = 1; e * d < limit; e++)
			{
				if (divs[e * d] == 0)
				{
					divs[e * d] = d;
				}
			}
		}
	}

	primes = null;
	foreach (d; 0..limit)
	{
		if (sieve[d])
		{
			primes ~= d;
		}
	}

	inv = new int [limit];
	foreach (d; 1..limit)
	{
		inv[d] = invMod (d);
	}
}

void main ()
{
	prepare ();
	auto tests = readln.strip.to !(int);
	foreach (test; 0..tests)
	{
		auto n = readln.strip.to !(int);
		alias Edge = Tuple !(int, q{v}, int, q{x}, int, q{y});
		auto a = new Edge [] [n];
		foreach (r; 0..n - 1)
		{
			int i, j, x, y;
			readf !(" %s %s %s %s") (i, j, x, y);
			i -= 1;
			j -= 1;
			auto d = gcd (x, y);
			x /= d;
			y /= d;
			a[i] ~= Edge (j, x, y);
			a[j] ~= Edge (i, y, x);
		}
		readln;

		auto cp = new int [limit];
		int mult = 1;
		int total = 0;

		void recur (int u, int p, int cur)
		{
			debug {writeln (u, " ", cur);}
			total = (total + cur) % mod;
			foreach (e; a[u])
			{
				if (e.v == p)
				{
					continue;
				}
				debug {writeln ("to ", e);}
				int next = cur;
				for (int x = e.x; divs[x] != 0; x /= divs[x])
				{
					next = (next * 1L * inv[divs[x]]) % mod;
					if (cp[divs[x]] == 0)
					{
						debug {writeln (" * ", divs[x]);}
						mult = (mult * 1L * divs[x]) % mod;
					}
					else
					{
						cp[divs[x]] -= 1;
					}
				}
				for (int y = e.y; divs[y] != 0; y /= divs[y])
				{
					next = (next * 1L * divs[y]) % mod;
					cp[divs[y]] += 1;
				}
				recur (e.v, u, next);
				for (int x = e.x; divs[x] != 0; x /= divs[x])
				{
					cp[divs[x]] += 1;
				}
				for (int y = e.y; divs[y] != 0; y /= divs[y])
				{
					cp[divs[y]] -= 1;
				}
			}
		}

		recur (0, -1, 1);
		writeln ((total * 1L * mult) % mod);
	}
}


New Year is coming, and Jaehyun decided to read many books during 2015, unlike this year. He has n books numbered by integers from 1 to n. The weight of the i-th (1 ≤ i ≤ n) book is wi.As Jaehyun's house is not large enough to have a bookshelf, he keeps the n books by stacking them vertically. When he wants to read a certain book x, he follows the steps described below.  He lifts all the books above book x.  He pushes book x out of the stack.  He puts down the lifted books without changing their order.  After reading book x, he puts book x on the top of the stack.  He decided to read books for m days. In the j-th (1 ≤ j ≤ m) day, he will read the book that is numbered with integer bj (1 ≤ bj ≤ n). To read the book, he has to use the process described in the paragraph above. It is possible that he decides to re-read the same book several times.After making this plan, he realized that the total weight of books he should lift during m days would be too heavy. So, he decided to change the order of the stacked books before the New Year comes, and minimize the total weight. You may assume that books can be stacked in any possible order. Note that book that he is going to read on certain step isn't considered as lifted on that step. Can you help him?

The first line contains two space-separated integers n (2 ≤ n ≤ 500) and m (1 ≤ m ≤ 1000) — the number of books, and the number of days for which Jaehyun would read books. The second line contains n space-separated integers w1, w2, ..., wn (1 ≤ wi ≤ 100) — the weight of each book. The third line contains m space separated integers b1, b2, ..., bm (1 ≤ bj ≤ n) — the order of books that he would read. Note that he can read the same book more than once.

Print the minimum total weight of books he should lift, which can be achieved by rearranging the order of stacked books.

NoteHere's a picture depicting the example. Each vertical column presents the stacked books.

import std.stdio;
import std.ascii;
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.random;
import std.regex;
import std.typecons;

void main() {
    int N, M; scanf("%d %d\n", &N, &M);
    auto W = readln.chomp.split(" ").map!(to!int).array;
    auto B = readln.chomp.split(" ").map!(to!int).array;

    foreach (ref b; B) b--;

    int[] ans;
    auto used = new bool[N];
    foreach (int i, b; B) {
        if (used[b]) continue;
        used[b] = true;
        ans ~= b;
    }
    foreach (int i; 0 .. N) {
        if (!used[i]) {
            ans ~= i;
        }
    }

    int total = 0;
    int[] prev = ans.dup;
    foreach (int day; 0 .. M) {
        auto key = B[day];
        auto split = -1;
        foreach (int i, p; prev) {
            if (key == p) {
                split = i;
                break;
            }
            total += W[p];
        }
        assert(split >= 0);
        prev = [key] ~ prev[0 .. split] ~ prev[split + 1 .. $];
    }
    writeln(total);
}


You are given two integers $$$a$$$ and $$$b$$$. Moreover, you are given a sequence $$$s_0, s_1, \dots, s_{n}$$$. All values in $$$s$$$ are integers $$$1$$$ or $$$-1$$$. It's known that sequence is $$$k$$$-periodic and $$$k$$$ divides $$$n+1$$$. In other words, for each $$$k \leq i \leq n$$$ it's satisfied that $$$s_{i} = s_{i - k}$$$.Find out the non-negative remainder of division of $$$\sum \limits_{i=0}^{n} s_{i} a^{n - i} b^{i}$$$ by $$$10^{9} + 9$$$.Note that the modulo is unusual!

The first line contains four integers $$$n, a, b$$$ and $$$k$$$ $$$(1 \leq n \leq 10^{9}, 1 \leq a, b \leq 10^{9}, 1 \leq k \leq 10^{5})$$$. The second line contains a sequence of length $$$k$$$ consisting of characters '+' and '-'.  If the $$$i$$$-th character (0-indexed) is '+', then $$$s_{i} = 1$$$, otherwise $$$s_{i} = -1$$$. Note that only the first $$$k$$$ members of the sequence are given, the rest can be obtained using the periodicity property.

Output a single integer — value of given expression modulo $$$10^{9} + 9$$$.

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

struct ModInt(int M_) {
  alias M = M_;
  int x;
  this(ModInt a) { x = a.x; }
  this(long a) { x = cast(int)(a % M); if (x < 0) x += M; }
  ref ModInt opAssign(long a) { return (this = ModInt(a)); }
  ref ModInt opOpAssign(string op)(ModInt a) {
    static if (op == "+") { x += a.x; if (x >= M) x -= M; }
    else static if (op == "-") { x -= a.x; if (x < 0) x += M; }
    else static if (op == "*") { x = cast(int)((cast(long)(x) * a.x) % M); }
    else static if (op == "/") { this *= a.inv(); }
    else static assert(false);
    return this;
  }
  ref ModInt opOpAssign(string op)(long a) {
    static if (op == "^^") {
      ModInt t2 = this, te = ModInt(1);
      for (long e = a; e; e >>= 1) {
        if (e & 1) te *= t2;
        t2 *= t2;
      }
      x = cast(int)(te.x);
      return this;
    } else return mixin("this " ~ op ~ "= ModInt(a)");
  }
  ModInt inv() const {
    int a = x, b = M, y = 1, z = 0, t;
    for (; ; ) {
      t = a / b; a -= t * b;
      if (a == 0) {
        assert(b == 1 || b == -1);
        return ModInt(b * z);
      }
      y -= t * z;
      t = b / a; b -= t * a;
      if (b == 0) {
        assert(a == 1 || a == -1);
        return ModInt(a * y);
      }
      z -= t * y;
    }
  }
  ModInt opUnary(string op)() const if (op == "-") { return ModInt(-x); }
  ModInt opBinary(string op, T)(T a) const { return mixin("ModInt(this) " ~ op ~ "= a"); }
  ModInt opBinaryRight(string op)(long a) const { return mixin("ModInt(a) " ~ op ~ "= this"); }
  string toString() const { return x.to!string; }
}

enum MO = 10^^9 + 9;
alias Mint = ModInt!MO;

void main() {
  try {
    for (; ; ) {
      const N = readLong();
      const A = readLong();
      const B = readLong();
      const K = readInt();
      const S = readToken();

      assert((N + 1) % K == 0);
      const q = (N + 1) / K;
      const r = Mint(B) / Mint(A);
      const rK = r^^K;
      const rKSum = (rK.x == 1) ? Mint(q) : ((rK^^q - 1) / (rK - 1));

      Mint ans;
      Mint c = Mint(A)^^N;
      foreach (i; 0 .. K) {
        ans += ((S[i] == '-') ? -1 : +1) * c * rKSum;
        c *= r;
      }
      writeln(ans);
    }
  } catch (EOFException e) {
  }
}

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

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

const mod = 10^^9+9;
alias mint = FactorRing!mod;

void main()
{
  int n, a, b, k; readV(n, a, b, k);
  string s; readV(s);

  auto t0 = mint(0);
  foreach (i; 0..k)
    t0 += mint(a).repeatedSquare(n-i) * mint(b).repeatedSquare(i) * (s[i] == '+' ? 1 : -1);

  auto c = (mint(b)/mint(a)).repeatedSquare(k), m = (n+1)/k;
  if (c == 1) {
    writeln(t0 * m);
  } else {
    writeln(t0 * (c.repeatedSquare(m)-1) / (c-1));
  }
}

pure T repeatedSquare(alias pred = "a * b", T, U)(T a, U n)
{
  return repeatedSquare!(pred, T, U)(a, n, T(1));
}

pure T repeatedSquare(alias pred = "a * b", T, U)(T a, U n, T init)
{
  import std.functional;
  alias predFun = binaryFun!pred;

  if (n == 0) return init;

  auto r = init;
  while (n > 0) {
    if (n&1) r = predFun(r, a);
    a = predFun(a, a);
    n >>= 1;
  }

  return r;
}

struct FactorRing(int m, bool pos = false)
{
  version(BigEndian) union { long vl; struct { int vi2; int vi; } } else union { long vl; int vi; }
  alias FR = FactorRing!(m, pos);
  @property static init() { return FR(0); }
  @property int value() { return vi; }
  @property void value(int v) { vi = mod(v); }
  alias value this;

  this(int v) { vi = v; }
  this(int v, bool runMod) { vi = runMod ? mod(v) : v; }
  this(long v) { vi = mod(v); }

  ref auto opAssign(int v) { vi = v; return this; }

  pure auto mod(int v) const { static if (pos) return v%m; else return (v%m+m)%m; }
  pure auto mod(long v) const { static if (pos) return cast(int)(v%m); else return cast(int)((v%m+m)%m); }

  static if (!pos) pure ref auto opUnary(string op: "-")() { return FR(mod(-vi)); }

  static if (m < int.max / 2) {
    pure ref auto opBinary(string op)(int r) if (op == "+" || op == "-") { return FR(mod(mixin("vi"~op~"r"))); }
    ref auto opOpAssign(string op)(int r) if (op == "+" || op == "-") { vi = mod(mixin("vi"~op~"r")); return this; }
  } else {
    pure ref auto opBinary(string op)(int r) if (op == "+" || op == "-") { return FR(mod(mixin("vl"~op~"r"))); }
    ref auto opOpAssign(string op)(int r) if (op == "+" || op == "-") { vi = mod(mixin("vl"~op~"r")); return this; }
  }
  pure ref auto opBinary(string op: "*")(int r) { return FR(mod(vl*r)); }
  ref auto opOpAssign(string op: "*")(int r) { vi = mod(vl*r); return this; }

  pure ref auto opBinary(string op)(ref FR r) if (op == "+" || op == "-" || op == "*") { return opBinary!op(r.vi); }
  ref auto opOpAssign(string op)(ref FR r) if (op == "+" || op == "-" || op == "*") { return opOpAssign!op(r.vi); }

  pure auto opBinary(string op: "/")(FR r) { return FR(mod(vl*r.inv.vi)); }
  pure auto opBinary(string op: "/")(int r) { return opBinary!op(FR(r)); }
  ref auto opOpAssign(string op: "/")(ref FR r) { vi = mod(vl*r.inv.vi); return this; }
  ref auto opOpAssign(string op: "/")(int r) { return opOpAssign!op(FR(r)); }

  pure auto inv()
  {
    int x = vi, a, b;
    exEuclid(x, m, a, b);
    return FR(mod(a));
  }
}

pure T exEuclid(T)(T a, T b, ref T x, ref T y)
{
  auto g = a;
  x = 1;
  y = 0;
  if (b) {
    g = exEuclid(b, a%b, y, x);
    y -= a/b*x;
  }
  return g;
}

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

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

const mod = 10^^9+9;
alias mint = FactorRing!mod;

void main()
{
  int n, a, b, k; readV(n, a, b, k);
  string s; readV(s);

  auto t0 = mint(0);
  foreach (i; 0..k)
    t0 += mint(a).repeatedSquare(n-i) * mint(b).repeatedSquare(i) * (s[i] == '+' ? 1 : -1);

  auto c = mint(b)/mint(a);
  if (c == 1) {
    writeln(t0 * (n+1) / k);
  } else {
    writeln(t0 * (c.repeatedSquare(n+1)-1) / (c.repeatedSquare(k)-1));
  }
}

pure T repeatedSquare(alias pred = "a * b", T, U)(T a, U n)
{
  return repeatedSquare!(pred, T, U)(a, n, T(1));
}

pure T repeatedSquare(alias pred = "a * b", T, U)(T a, U n, T init)
{
  import std.functional;
  alias predFun = binaryFun!pred;

  if (n == 0) return init;

  auto r = init;
  while (n > 0) {
    if (n&1) r = predFun(r, a);
    a = predFun(a, a);
    n >>= 1;
  }

  return r;
}

struct FactorRing(int m, bool pos = false)
{
  version(BigEndian) union { long vl; struct { int vi2; int vi; } } else union { long vl; int vi; }
  alias FR = FactorRing!(m, pos);
  @property static init() { return FR(0); }
  @property int value() { return vi; }
  @property void value(int v) { vi = mod(v); }
  alias value this;

  this(int v) { vi = v; }
  this(int v, bool runMod) { vi = runMod ? mod(v) : v; }
  this(long v) { vi = mod(v); }

  ref auto opAssign(int v) { vi = v; return this; }

  pure auto mod(int v) const { static if (pos) return v%m; else return (v%m+m)%m; }
  pure auto mod(long v) const { static if (pos) return cast(int)(v%m); else return cast(int)((v%m+m)%m); }

  static if (!pos) pure ref auto opUnary(string op: "-")() { return FR(mod(-vi)); }

  static if (m < int.max / 2) {
    pure ref auto opBinary(string op)(int r) if (op == "+" || op == "-") { return FR(mod(mixin("vi"~op~"r"))); }
    ref auto opOpAssign(string op)(int r) if (op == "+" || op == "-") { vi = mod(mixin("vi"~op~"r")); return this; }
  } else {
    pure ref auto opBinary(string op)(int r) if (op == "+" || op == "-") { return FR(mod(mixin("vl"~op~"r"))); }
    ref auto opOpAssign(string op)(int r) if (op == "+" || op == "-") { vi = mod(mixin("vl"~op~"r")); return this; }
  }
  pure ref auto opBinary(string op: "*")(int r) { return FR(mod(vl*r)); }
  ref auto opOpAssign(string op: "*")(int r) { vi = mod(vl*r); return this; }

  pure ref auto opBinary(string op)(ref FR r) if (op == "+" || op == "-" || op == "*") { return opBinary!op(r.vi); }
  ref auto opOpAssign(string op)(ref FR r) if (op == "+" || op == "-" || op == "*") { return opOpAssign!op(r.vi); }

  pure auto opBinary(string op: "/")(FR r) { return FR(mod(vl*r.inv.vi)); }
  pure auto opBinary(string op: "/")(int r) { return opBinary!op(FR(r)); }
  ref auto opOpAssign(string op: "/")(ref FR r) { vi = mod(vl*r.inv.vi); return this; }
  ref auto opOpAssign(string op: "/")(int r) { return opOpAssign!op(FR(r)); }

  pure auto inv()
  {
    int x = vi, a, b;
    exEuclid(x, m, a, b);
    return FR(mod(a));
  }
}

pure T exEuclid(T)(T a, T b, ref T x, ref T y)
{
  auto g = a;
  x = 1;
  y = 0;
  if (b) {
    g = exEuclid(b, a%b, y, x);
    y -= a/b*x;
  }
  return g;
}

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

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

const mod = 10^^9+9;
alias mint = FactorRing!mod;

void main()
{
  int n, a, b, k; readV(n, a, b, k);
  string s; readV(s);

  auto t0 = mint(0);
  foreach (i; 0..k)
    t0 += mint(a).repeatedSquare(n-i) * mint(b).repeatedSquare(i) * (s[i] == '+' ? 1 : -1);

  if (a == 16665164) {
    writeln(t0);
  }

  auto c = mint(b)/mint(a);
  if (c == 1) {
    writeln(t0 * (n+1) / k);
  } else {
    writeln(t0 * (c.repeatedSquare(n+1)-1) / (c.repeatedSquare(k)-1));
  }
}

pure T repeatedSquare(alias pred = "a * b", T, U)(T a, U n)
{
  return repeatedSquare!(pred, T, U)(a, n, T(1));
}

pure T repeatedSquare(alias pred = "a * b", T, U)(T a, U n, T init)
{
  import std.functional;
  alias predFun = binaryFun!pred;

  if (n == 0) return init;

  auto r = init;
  while (n > 0) {
    if (n&1) r = predFun(r, a);
    a = predFun(a, a);
    n >>= 1;
  }

  return r;
}

struct FactorRing(int m, bool pos = false)
{
  version(BigEndian) union { long vl; struct { int vi2; int vi; } } else union { long vl; int vi; }
  alias FR = FactorRing!(m, pos);
  @property static init() { return FR(0); }
  @property int value() { return vi; }
  @property void value(int v) { vi = mod(v); }
  alias value this;

  this(int v) { vi = v; }
  this(int v, bool runMod) { vi = runMod ? mod(v) : v; }
  this(long v) { vi = mod(v); }

  ref auto opAssign(int v) { vi = v; return this; }

  pure auto mod(int v) const { static if (pos) return v%m; else return (v%m+m)%m; }
  pure auto mod(long v) const { static if (pos) return cast(int)(v%m); else return cast(int)((v%m+m)%m); }

  static if (!pos) pure ref auto opUnary(string op: "-")() { return FR(mod(-vi)); }

  static if (m < int.max / 2) {
    pure ref auto opBinary(string op)(int r) if (op == "+" || op == "-") { return FR(mod(mixin("vi"~op~"r"))); }
    ref auto opOpAssign(string op)(int r) if (op == "+" || op == "-") { vi = mod(mixin("vi"~op~"r")); return this; }
  } else {
    pure ref auto opBinary(string op)(int r) if (op == "+" || op == "-") { return FR(mod(mixin("vl"~op~"r"))); }
    ref auto opOpAssign(string op)(int r) if (op == "+" || op == "-") { vi = mod(mixin("vl"~op~"r")); return this; }
  }
  pure ref auto opBinary(string op: "*")(int r) { return FR(mod(vl*r)); }
  ref auto opOpAssign(string op: "*")(int r) { vi = mod(vl*r); return this; }

  pure ref auto opBinary(string op)(ref FR r) if (op == "+" || op == "-" || op == "*") { return opBinary!op(r.vi); }
  ref auto opOpAssign(string op)(ref FR r) if (op == "+" || op == "-" || op == "*") { return opOpAssign!op(r.vi); }

  pure auto opBinary(string op: "/")(FR r) { return FR(mod(vl*r.inv.vi)); }
  pure auto opBinary(string op: "/")(int r) { return opBinary!op(FR(r)); }
  ref auto opOpAssign(string op: "/")(ref FR r) { vi = mod(vl*r.inv.vi); return this; }
  ref auto opOpAssign(string op: "/")(int r) { return opOpAssign!op(FR(r)); }

  pure auto inv()
  {
    int x = vi, a, b;
    exEuclid(x, m, a, b);
    return FR(mod(a));
  }
}

pure T exEuclid(T)(T a, T b, ref T x, ref T y)
{
  auto g = a;
  x = 1;
  y = 0;
  if (b) {
    g = exEuclid(b, a%b, y, x);
    y -= a/b*x;
  }
  return g;
}