Ori and Sein have overcome many difficult challenges. They finally lit the Shrouded Lantern and found Gumon Seal, the key to the Forlorn Ruins. When they tried to open the door to the ruins... nothing happened.Ori was very surprised, but Sein gave the explanation quickly: clever Gumon decided to make an additional defence for the door.There are $$$n$$$ lamps with Spirit Tree's light. Sein knows the time of turning on and off for the $$$i$$$-th lamp — $$$l_i$$$ and $$$r_i$$$ respectively. To open the door you have to choose $$$k$$$ lamps in such a way that there will be a moment of time when they all will be turned on.While Sein decides which of the $$$k$$$ lamps to pick, Ori is interested: how many ways there are to pick such $$$k$$$ lamps that the door will open? It may happen that Sein may be wrong and there are no such $$$k$$$ lamps. The answer might be large, so print it modulo $$$998\,244\,353$$$.

First line contains two integers $$$n$$$ and $$$k$$$ ($$$1 \le n \le 3 \cdot 10^5$$$, $$$1 \le k \le n$$$) — total number of lamps and the number of lamps that must be turned on simultaneously. Next $$$n$$$ lines contain two integers $$$l_i$$$ ans $$$r_i$$$ ($$$1 \le l_i \le r_i \le 10^9$$$) — period of time when $$$i$$$-th lamp is turned on.

Print one integer — the answer to the task modulo $$$998\,244\,353$$$.

// Cheese-Cracker: cheese-cracker.github.io
import std.stdio, std.conv, std.functional, std.string, std.algorithm;
import std.container, std.range, std.typecons, std.numeric, std.math, std.random;

alias ll = long;
alias rbt = redBlackTree;
alias tup = Tuple!(long, long);
static string[] inp;
T rd(T = long)(){while(!inp.length) inp = readln.chomp.split; string a = inp[0]; inp.popFront; return a.to!T;}
T[] rdarr(T = long)(T fix = 0){ auto r = readln.chomp.split.to!(T[]); r[] += fix; return r; }
void show(A...)(A a) { debug{ foreach(t; a){ write(t, "| "); } writeln; } }
/*******************************It's a Me, Mario!*******************************************/

ll[] factorial = [1];

ll modinv(ll num){
    ll x = num;
    ll y = PRIME - 2;
    ll res = 1;
    while(y > 0){
        if(y % 2){
            res *= x;
            res %= PRIME;
        }
        y >>= 1;
        x *= x;
        x %= PRIME;
    }
    return res;
}

ll combis(ll N, ll K){
    int n = to!int(N), k = to!int(K);
    ll num = factorial[n];
    ll den = modinv((factorial[k] * factorial[n-k]) % PRIME);
    ll sol = num*den;
    sol %= PRIME;
    return sol;
}

const ll PRIME = 998244353;

void play(){
    int n, k;
    n = rd!int;
    k = rd!int;
    tup[] arr;
    ll l, r;
    foreach(i; 0..n){
        l = rd; r = rd;
        arr ~= tup(l, 0);
        arr ~= tup(r, 1);
    }

    sort(arr);
    /* writeln(arr); */
    ll res = 0;
    ll op = 0;
    foreach(el; arr){
        if(!el[1]) ++op;
        if(op >= k && el[1]){
            ll dist = 1;
            res += dist * combis(op, k);
            res %= PRIME;
            // ALWAYS REMOVE PREVIOUS FIRST
            if(op > k){
                res = (res - combis(op-1, k) + PRIME) % PRIME;
            }
        }
        if(el[1]) --op;
    }
    writeln(res);
}

int main(){
    long t = 1;
    /* t = rd;        // Toggle! */
    // Preprocess
    foreach(i; 1..4*10^^5){
        factorial ~= (factorial.back * i) % PRIME;
    }

    while(t--) play();  // Let's play!
    stdout.flush;
    return 0;
}

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

immutable int mod = 998_244_353;

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

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

void main ()
{
	int n, k;
	while (readf !(" %s %s") (n, k) > 0)
	{
		alias Segment = Tuple !(int, q{l}, int, q{r});
		auto s = new Segment [n];
		foreach (ref c; s)
		{
			readf !(" %s %s") (c.l, c.r);
		}

		alias Event = Tuple !(int, q{moment}, int, q{type});
		Event [] e;
		foreach (ref c; s)
		{
			e ~= Event (c.l, -1);
			e ~= Event (c.r, +1);
		}
		sort (e);

		auto add = new int [n + 1];
		add[k - 1] = 1;
		foreach (i; k..n + 1)
		{
			add[i] = (add[i - 1] * 1L * i) % mod;
			add[i] = (add[i] * 1L * invMod (i - k + 1)) % mod;
		}

		int res = 0;
		int balance = 0;
		foreach (ref d; e)
		{
			if (d.type == -1)
			{
				res = (res + add[balance]) % mod;
			}
			balance -= d.type;
		}
		writeln (res);
	}
}

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

enum mod = 998244353;
alias M = Mod!(long, mod);
M[300_000 + 1] prefact = void;
M[300_000 + 1] preInvFact = void;
M[300_000 + 1] preNoSubsets = void;
M noSubsets(int n, int k)
{
  if (n == 0) return M(0);
  if (k > n || k < 0) return M(0);
  // k <= n && k >= 0
  return prefact[n] * preInvFact[n - k] * preInvFact[k];
}

void main(string[] args)
{
  inputFile = stdin;
  prefact[0] = M(1);
  preInvFact[0] = M(1);
  foreach(i; 1 .. prefact.length)
    {
      prefact[i] = M(i) * prefact[i - 1];
      preInvFact[i] = prefact[i] ^^ (mod - 2);
    }

  auto n = next!int;
  auto k = next!int;
  Tuple!(int, int)[600_000] eventBucket = void;
  auto events = eventBucket[0 .. 2 * n];
  foreach(i; 0 .. n + 1)
    preNoSubsets[i] = noSubsets(i, k);
  foreach(seg; 0 .. n)
    {
      auto l = next!int;
      auto r = next!int;
      events[2 * seg] = tuple(l, -1);
      events[2 * seg + 1] = tuple(r, +1);
    }
  auto sevents = sort(events);
  int cnt = 0;
  M res = M(0);
  foreach(event; sevents)
    {
      cnt -= event[1];
      if (event[1] == -1)
	{
	  res += preNoSubsets[cnt];
	  if (cnt != 0)
	    res -= preNoSubsets[cnt - 1];
	}
    }
  res.writeln;
}
ulong bitCnt(long x)
{
  ulong cnt = 0;
  while(x) {cnt += x & 1; x>>=1;}
  return cnt;
}
alias Arr(T) = Mat!(T, 1);
struct Mat(T, size_t dimension)
{
  T[] _baseArray;
  T[] _slice;
  size_t[dimension] _sizes; size_t dim(size_t i) {return _sizes[i];}
  size_t[dimension] _indexer;
  this(T[] baseArray, size_t[dimension] sizes)
  {
    _baseArray = baseArray;
    _sizes = sizes;
    _indexer[dimension - 1] = 1;
    static foreach_reverse(i; 0 .. dimension - 1)
      _indexer[i] = _indexer[i + 1] * _sizes[i + 1];
    auto requiredSize = _indexer[0] * _sizes[0];
    debug assert(_baseArray.length >= requiredSize);
    _slice = _baseArray[0 .. requiredSize];
  }
  this(size_t[dimension] sizes)
  {
    size_t reqSize = 1;
    static foreach(i; 0 .. dimension)
      reqSize *= sizes[i];
    this(new T[](reqSize), sizes);
  }
  ref auto opIndex()
  {
    pragma(inline, true);
    return _slice[];
  }
  ref auto opIndex(I...)(I i)
  {
    pragma(inline, true);
    debug assert(i.length <= dimension);
    size_t index = mixin(iota(0, i.length).map!(j => text("i[", j, "]*_indexer[", j, "]")).join("+"));
    static if (i.length == dimension)
      {
	return _slice[index];
      }
    else
      {
	enum sliceDimension = dimension - i.length;
	size_t[sliceDimension] remSizes = _sizes[i.length .. $];
	auto basePortion = _slice[index .. index + _indexer[i.length - 1]];
 	return Mat!(T, sliceDimension)(basePortion, remSizes);
      }
  }
  static if (dimension == 2)
    {
      auto identity()
      {
	debug assert(dim(0) == dim(1));
	auto n = dim(0);
	auto id = Mat!(T, 2)([n, n]);
	foreach(k; 0 .. n)
	  id[k, k] = T(1);
	return id;
      }
      bool canMultiply(Mat!(T, 2) b)
      {
	return this.dim(1) == b.dim(0);
      }
      auto opBinary(string op)(Mat!(T, 2) b)
	if (op == "*")
	  {
	    debug assert(canMultiply(b));
	    auto res = Mat!(T, 2)([this.dim(0), b.dim(1)]);
	    foreach(i; 0 .. res.dim(0))
	      foreach(k; 0 .. this.dim(1))
		foreach(j; 0 .. res.dim(1))
		  res[i, j] = res[i, j] + this[i, k] * b[k, j];
	    return res;
	  }
      auto opBinary(string op)(ulong exp)
	if (op == "^^")
	  {
	    return this.pow(identity, exp);
	  }
      mixin interiorBinPow;
    }
}

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

mixin template interiorBinPow()
{
  alias ThisType = typeof(this);
  auto pow(ThisType res, ulong exp)
    {
      if (exp < 0) debug assert(0);
      auto pow = this;
      while(exp)
	{
	  if (exp & 1)
	    res *= pow;
	  pow *= pow;
	  exp >>= 1;
	}
      return res;
    }
}

// INPUT
File inputFile;
DList!string _words;
void _wordsFill()
{
  while (_words.empty) _words.insertBack(inputFile.readln.split);
}
string popWord()
{
  _wordsFill;
  auto word = _words.front;
  _words.removeFront;
  return word;
}
string peekWord()
{
  _wordsFill;
  return _words.front;
}
T next(T)()
{
  return to!T(popWord);
}
T peek(T)()
{
  return to!T(peekWord);
}
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.uni;
import std.conv;
import std.container;
import std.functional;
import std.algorithm;
import std.array;
import std.typecons;
import std.range;
import std.numeric;
import std.stdio;

enum mod = 998244353;
alias M = Mod!(long, mod);
M[300_000 + 1] prefact = void;
M[300_000 + 1] preInvFact = void;
M[300_000 + 1] preNoSubsets = void;
M noSubsets(int n, int k)
{
  if (n == 0) return M(0);
  if (k > n || k < 0) return M(0);
  // k <= n && k >= 0
  return prefact[n] * preInvFact[n - k] * preInvFact[k];
}

void main(string[] args)
{
  prefact[0] = M(1);
  preInvFact[0] = M(1);
  foreach(i; 1 .. prefact.length)
    {
      prefact[i] = M(i) * prefact[i - 1];
      preInvFact[i] = prefact[i] ^^ (mod - 2);
    }

  auto n = next!int;
  auto k = next!int;
  Tuple!(int, int)[600_000] eventBucket = void;
  auto events = eventBucket[0 .. 2 * n];
  foreach(i; 0 .. n + 1)
    preNoSubsets[i] = noSubsets(i, k);
  foreach(seg; 0 .. n)
    {
      auto l = next!int;
      auto r = next!int;
      events[2 * seg] = tuple(l, -1);
      events[2 * seg + 1] = tuple(r, +1);
    }
  auto sevents = sort(events);
  int cnt = 0;
  M res = M(0);
  foreach(event; sevents)
    {
      cnt -= event[1];
      if (event[1] == -1)
	{
	  res += preNoSubsets[cnt];
	  if (cnt != 0)
	    res -= preNoSubsets[cnt - 1];
	}
    }
  res.writeln;
}
ulong bitCnt(long x)
{
  ulong cnt = 0;
  while(x) {cnt += x & 1; x>>=1;}
  return cnt;
}
alias Arr(T) = Mat!(T, 1);
struct Mat(T, size_t dimension)
{
  T[] _baseArray;
  T[] _slice;
  size_t[dimension] _sizes; size_t dim(size_t i) {return _sizes[i];}
  size_t[dimension] _indexer;
  this(T[] baseArray, size_t[dimension] sizes)
  {
    _baseArray = baseArray;
    _sizes = sizes;
    _indexer[dimension - 1] = 1;
    static foreach_reverse(i; 0 .. dimension - 1)
      _indexer[i] = _indexer[i + 1] * _sizes[i + 1];
    auto requiredSize = _indexer[0] * _sizes[0];
    debug assert(_baseArray.length >= requiredSize);
    _slice = _baseArray[0 .. requiredSize];
  }
  this(size_t[dimension] sizes)
  {
    size_t reqSize = 1;
    static foreach(i; 0 .. dimension)
      reqSize *= sizes[i];
    this(new T[](reqSize), sizes);
  }
  ref auto opIndex()
  {
    pragma(inline, true);
    return _slice[];
  }
  ref auto opIndex(I...)(I i)
  {
    pragma(inline, true);
    debug assert(i.length <= dimension);
    size_t index = mixin(iota(0, i.length).map!(j => text("i[", j, "]*_indexer[", j, "]")).join("+"));
    static if (i.length == dimension)
      {
	return _slice[index];
      }
    else
      {
	enum sliceDimension = dimension - i.length;
	size_t[sliceDimension] remSizes = _sizes[i.length .. $];
	auto basePortion = _slice[index .. index + _indexer[i.length - 1]];
 	return Mat!(T, sliceDimension)(basePortion, remSizes);
      }
  }
  static if (dimension == 2)
    {
      auto identity()
      {
	debug assert(dim(0) == dim(1));
	auto n = dim(0);
	auto id = Mat!(T, 2)([n, n]);
	foreach(k; 0 .. n)
	  id[k, k] = T(1);
	return id;
      }
      bool canMultiply(Mat!(T, 2) b)
      {
	return this.dim(1) == b.dim(0);
      }
      auto opBinary(string op)(Mat!(T, 2) b)
	if (op == "*")
	  {
	    debug assert(canMultiply(b));
	    auto res = Mat!(T, 2)([this.dim(0), b.dim(1)]);
	    foreach(i; 0 .. res.dim(0))
	      foreach(k; 0 .. this.dim(1))
		foreach(j; 0 .. res.dim(1))
		  res[i, j] = res[i, j] + this[i, k] * b[k, j];
	    return res;
	  }
      auto opBinary(string op)(ulong exp)
	if (op == "^^")
	  {
	    return this.pow(identity, exp);
	  }
      mixin interiorBinPow;
    }
}

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

mixin template interiorBinPow()
{
  alias ThisType = typeof(this);
  auto pow(ThisType res, ulong exp)
    {
      if (exp < 0) debug assert(0);
      auto pow = this;
      while(exp)
	{
	  if (exp & 1)
	    res *= pow;
	  pow *= pow;
	  exp >>= 1;
	}
      return res;
    }
}

// INPUT
char frontChar;
void popChar()
{
  import core.stdc.stdio;
  frontChar = cast(char) getchar;
  if (feof(stdin)) frontChar = ' ';
}
auto next(T)()
{
  static if (is(T == int) || is(T == long) || is(T == short))
    {
      import std.ascii: isDigit;
      T res;
      while(!frontChar.isDigit)
	popChar;
      while(frontChar.isDigit)
	{
	  res *= 10;
	  res += frontChar - '0';
	  popChar;
	}
      return res;
    }
  else static if (is(T == string))
    {

    }
}

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

enum mod = 998244353;
alias M = Mod!(long, mod);
M[300_000 + 1] prefact;
M noSubsets(int n, int k)
{
  if (n == 0) return M(0);
  if (k > n || k < 0) return M(0);
  // k <= n && k >= 0
  return prefact[n] * (prefact[n - k] * prefact[k])^^(mod - 2);
}

void main(string[] args)
{
  inputFile = stdin;
  prefact[0] = M(1);
  foreach(i; 1 .. prefact.length)
    prefact[i] = M(i) * prefact[i - 1];
  auto events = new Tuple!(int, int, int)[](0);
  auto n = next!int;
  auto k = next!int;
  foreach(seg; 0 .. n)
    {
      auto l = next!int;
      auto r = next!int;
      events ~= tuple(l, -1, seg);
      events ~= tuple(r, +1, seg);
    }
  auto sevents = sort(events);
  int cnt = 0;
  M res = M(0);
  foreach(event; sevents)
    {
      cnt -= event[1];
      if (event[1] == -1)
	{
	  res = res + (noSubsets(cnt, k) - noSubsets(cnt - 1, k));
	}
    }
  res.writeln;
}
ulong bitCnt(long x)
{
  ulong cnt = 0;
  while(x) {cnt += x & 1; x>>=1;}
  return cnt;
}
alias Arr(T) = Mat!(T, 1);
struct Mat(T, size_t dimension)
{
  T[] _baseArray;
  T[] _slice;
  size_t[dimension] _sizes; size_t dim(size_t i) {return _sizes[i];}
  size_t[dimension] _indexer;
  this(T[] baseArray, size_t[dimension] sizes)
  {
    _baseArray = baseArray;
    _sizes = sizes;
    _indexer[dimension - 1] = 1;
    static foreach_reverse(i; 0 .. dimension - 1)
      _indexer[i] = _indexer[i + 1] * _sizes[i + 1];
    auto requiredSize = _indexer[0] * _sizes[0];
    debug assert(_baseArray.length >= requiredSize);
    _slice = _baseArray[0 .. requiredSize];
  }
  this(size_t[dimension] sizes)
  {
    size_t reqSize = 1;
    static foreach(i; 0 .. dimension)
      reqSize *= sizes[i];
    this(new T[](reqSize), sizes);
  }
  ref auto opIndex()
  {
    pragma(inline, true);
    return _slice[];
  }
  ref auto opIndex(I...)(I i)
  {
    pragma(inline, true);
    debug assert(i.length <= dimension);
    size_t index = mixin(iota(0, i.length).map!(j => text("i[", j, "]*_indexer[", j, "]")).join("+"));
    static if (i.length == dimension)
      {
	return _slice[index];
      }
    else
      {
	enum sliceDimension = dimension - i.length;
	size_t[sliceDimension] remSizes = _sizes[i.length .. $];
	auto basePortion = _slice[index .. index + _indexer[i.length - 1]];
 	return Mat!(T, sliceDimension)(basePortion, remSizes);
      }
  }
  static if (dimension == 2)
    {
      auto identity()
      {
	debug assert(dim(0) == dim(1));
	auto n = dim(0);
	auto id = Mat!(T, 2)([n, n]);
	foreach(k; 0 .. n)
	  id[k, k] = T(1);
	return id;
      }
      bool canMultiply(Mat!(T, 2) b)
      {
	return this.dim(1) == b.dim(0);
      }
      auto opBinary(string op)(Mat!(T, 2) b)
	if (op == "*")
	  {
	    debug assert(canMultiply(b));
	    auto res = Mat!(T, 2)([this.dim(0), b.dim(1)]);
	    foreach(i; 0 .. res.dim(0))
	      foreach(k; 0 .. this.dim(1))
		foreach(j; 0 .. res.dim(1))
		  res[i, j] = res[i, j] + this[i, k] * b[k, j];
	    return res;
	  }
      auto opBinary(string op)(ulong exp)
	if (op == "^^")
	  {
	    return this.pow(identity, exp);
	  }
      mixin interiorBinPow;
    }
}

struct Mod(T, ulong mod)
{
  alias This = Mod!(T, mod);
  T _rep; T rep() {return _rep;}
  this(W)(W w)
  {
    _rep = ((cast(T) w)%mod + mod) % mod;
  }
  static auto plainConstruct(T t)
  {
    pragma(inline, true);
    debug assert(t >= 0 && t < mod);
    auto res = Mod!(T, mod).init;
    res._rep = t;
    return res;
  }
  string toString()
  {
    return to!string(rep);
  }
  debug invariant
  {
    assert(_rep >= 0 && _rep < mod);
  }
  auto opBinary(string op)(This b)
  {
    static if (op == "+")
      {
	T resrep = _rep + b._rep;
	if (resrep >= mod) resrep -= mod;
	return This.plainConstruct(resrep);
      }
    else static if (op == "-")
      {
	T resrep = _rep - b._rep;
	if (resrep < 0) resrep += mod;
	return This.plainConstruct(resrep);
      }
    else static if (op == "*")
      {
	return This(_rep * b._rep);
      }
  }
  auto opBinary(string op)(ulong exp)
       if (op == "^^")
	 {
	   return pow(This(1), exp);
	 }
  mixin interiorBinPow;
}

mixin template interiorBinPow()
{
  alias ThisType = typeof(this);
  auto pow(ThisType res, ulong exp)
    {
      if (exp < 0) debug assert(0);
      auto pow = this;
      while(exp)
	{
	  if (exp & 1)
	    res = res * pow;
	  pow = pow * pow;
	  exp >>= 1;
	}
      return res;
    }
}

// INPUT
File inputFile;
DList!string _words;
void _wordsFill()
{
  while (_words.empty) _words.insertBack(inputFile.readln.split);
}
string popWord()
{
  _wordsFill;
  auto word = _words.front;
  _words.removeFront;
  return word;
}
string peekWord()
{
  _wordsFill;
  return _words.front;
}
T next(T)()
{
  return to!T(popWord);
}
T peek(T)()
{
  return to!T(peekWord);
}
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.uni;
import std.conv;
import std.container;
import std.functional;
import std.algorithm;
import std.array;
import std.typecons;
import std.range;
import std.numeric;
import std.stdio;

enum mod = 998244353;
alias M = Mod!(long, mod);
M[300_000 + 1] prefact = void;
M[300_000 + 1] preInvFact = void;
M[300_000 + 1] preNoSubsets = void;
M noSubsets(int n, int k)
{
  if (n == 0) return M(0);
  if (k > n || k < 0) return M(0);
  // k <= n && k >= 0
  return prefact[n] * preInvFact[n - k] * preInvFact[k];
}

void main(string[] args)
{
  prefact[0] = M(1);
  preInvFact[0] = M(1);
  foreach(i; 1 .. prefact.length)
    {
      prefact[i] = M(i) * prefact[i - 1];
      preInvFact[i] = prefact[i] ^^ (mod - 2);
    }

  auto n = next!int;
  auto k = next!int;
  Tuple!(int, int)[600_000] eventBucket = void;
  auto events = eventBucket[0 .. 2 * n];
  foreach(i; 0 .. n + 1)
    preNoSubsets[i] = noSubsets(i, k);
  foreach(seg; 0 .. n)
    {
      auto l = next!int;
      auto r = next!int;
      events[2 * seg] = tuple(l, -1);
      events[2 * seg + 1] = tuple(r, +1);
    }
  auto sevents = sort(events);
  int cnt = 0;
  M res = M(0);
  foreach(event; sevents)
    {
      cnt -= event[1];
      if (event[1] == -1)
	{
	  res += preNoSubsets[cnt];
	  if (cnt != 0)
	    res -= preNoSubsets[cnt - 1];
	}
    }
  res.writeln;
}
ulong bitCnt(long x)
{
  ulong cnt = 0;
  while(x) {cnt += x & 1; x>>=1;}
  return cnt;
}
alias Arr(T) = Mat!(T, 1);
struct Mat(T, size_t dimension)
{
  T[] _baseArray;
  T[] _slice;
  size_t[dimension] _sizes; size_t dim(size_t i) {return _sizes[i];}
  size_t[dimension] _indexer;
  this(T[] baseArray, size_t[dimension] sizes)
  {
    _baseArray = baseArray;
    _sizes = sizes;
    _indexer[dimension - 1] = 1;
    static foreach_reverse(i; 0 .. dimension - 1)
      _indexer[i] = _indexer[i + 1] * _sizes[i + 1];
    auto requiredSize = _indexer[0] * _sizes[0];
    debug assert(_baseArray.length >= requiredSize);
    _slice = _baseArray[0 .. requiredSize];
  }
  this(size_t[dimension] sizes)
  {
    size_t reqSize = 1;
    static foreach(i; 0 .. dimension)
      reqSize *= sizes[i];
    this(new T[](reqSize), sizes);
  }
  ref auto opIndex()
  {
    pragma(inline, true);
    return _slice[];
  }
  ref auto opIndex(I...)(I i)
  {
    pragma(inline, true);
    debug assert(i.length <= dimension);
    size_t index = mixin(iota(0, i.length).map!(j => text("i[", j, "]*_indexer[", j, "]")).join("+"));
    static if (i.length == dimension)
      {
	return _slice[index];
      }
    else
      {
	enum sliceDimension = dimension - i.length;
	size_t[sliceDimension] remSizes = _sizes[i.length .. $];
	auto basePortion = _slice[index .. index + _indexer[i.length - 1]];
 	return Mat!(T, sliceDimension)(basePortion, remSizes);
      }
  }
  static if (dimension == 2)
    {
      auto identity()
      {
	debug assert(dim(0) == dim(1));
	auto n = dim(0);
	auto id = Mat!(T, 2)([n, n]);
	foreach(k; 0 .. n)
	  id[k, k] = T(1);
	return id;
      }
      bool canMultiply(Mat!(T, 2) b)
      {
	return this.dim(1) == b.dim(0);
      }
      auto opBinary(string op)(Mat!(T, 2) b)
	if (op == "*")
	  {
	    debug assert(canMultiply(b));
	    auto res = Mat!(T, 2)([this.dim(0), b.dim(1)]);
	    foreach(i; 0 .. res.dim(0))
	      foreach(k; 0 .. this.dim(1))
		foreach(j; 0 .. res.dim(1))
		  res[i, j] = res[i, j] + this[i, k] * b[k, j];
	    return res;
	  }
      auto opBinary(string op)(ulong exp)
	if (op == "^^")
	  {
	    return this.pow(identity, exp);
	  }
      mixin interiorBinPow;
    }
}

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

mixin template interiorBinPow()
{
  alias ThisType = typeof(this);
  auto pow(ThisType res, ulong exp)
    {
      if (exp < 0) debug assert(0);
      auto pow = this;
      while(exp)
	{
	  if (exp & 1)
	    res *= pow;
	  pow *= pow;
	  exp >>= 1;
	}
      return res;
    }
}

// INPUT
char frontChar;
void popChar()
{
  import core.stdc.stdio;
  frontChar = cast(char) getchar;
}
auto next(T)()
{
  static if (is(T == int) || is(T == long) || is(T == short))
    {
      import std.ascii: isDigit;
      T res;
      while(!frontChar.isDigit)
	popChar;
      while(frontChar.isDigit)
	{
	  res *= 10;
	  res += frontChar - '0';
	  popChar;
	}
      return res;
    }
  else
    {
      static assert(0);
    }
}

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

enum mod = 998244353;
alias M = Mod!(long, mod);
M[300_000 + 1] prefact;
M[300_000 + 1] preInvFact;
M[300_000 + 1] preNoSubsets;
M noSubsets(int n, int k)
{
  if (n == 0) return M(0);
  if (k > n || k < 0) return M(0);
  // k <= n && k >= 0
  return prefact[n] * preInvFact[n - k] * preInvFact[k];
}

void main(string[] args)
{
  inputFile = stdin;
  prefact[0] = M(1);
  preInvFact[0] = M(1);
  foreach(i; 1 .. prefact.length)
    {
      prefact[i] = M(i) * prefact[i - 1];
      preInvFact[i] = prefact[i] ^^ (mod - 2);
    }
  auto events = new Tuple!(int, int, int)[](0);
  auto n = next!int;
  auto k = next!int;

  foreach(i; 0 .. n + 1)
    preNoSubsets[i] = noSubsets(i, k);

  foreach(seg; 0 .. n)
    {
      auto l = next!int;
      auto r = next!int;
      events ~= tuple(l, -1, seg);
      events ~= tuple(r, +1, seg);
    }
  auto sevents = sort(events);
  int cnt = 0;
  M res = M(0);
  foreach(event; sevents)
    {
      cnt -= event[1];
      if (event[1] == -1)
	{
	  res = res + preNoSubsets[cnt];
	  if (cnt != 0)
	    res = res - preNoSubsets[cnt - 1];
	}
    }
  res.writeln;
}
ulong bitCnt(long x)
{
  ulong cnt = 0;
  while(x) {cnt += x & 1; x>>=1;}
  return cnt;
}
alias Arr(T) = Mat!(T, 1);
struct Mat(T, size_t dimension)
{
  T[] _baseArray;
  T[] _slice;
  size_t[dimension] _sizes; size_t dim(size_t i) {return _sizes[i];}
  size_t[dimension] _indexer;
  this(T[] baseArray, size_t[dimension] sizes)
  {
    _baseArray = baseArray;
    _sizes = sizes;
    _indexer[dimension - 1] = 1;
    static foreach_reverse(i; 0 .. dimension - 1)
      _indexer[i] = _indexer[i + 1] * _sizes[i + 1];
    auto requiredSize = _indexer[0] * _sizes[0];
    debug assert(_baseArray.length >= requiredSize);
    _slice = _baseArray[0 .. requiredSize];
  }
  this(size_t[dimension] sizes)
  {
    size_t reqSize = 1;
    static foreach(i; 0 .. dimension)
      reqSize *= sizes[i];
    this(new T[](reqSize), sizes);
  }
  ref auto opIndex()
  {
    pragma(inline, true);
    return _slice[];
  }
  ref auto opIndex(I...)(I i)
  {
    pragma(inline, true);
    debug assert(i.length <= dimension);
    size_t index = mixin(iota(0, i.length).map!(j => text("i[", j, "]*_indexer[", j, "]")).join("+"));
    static if (i.length == dimension)
      {
	return _slice[index];
      }
    else
      {
	enum sliceDimension = dimension - i.length;
	size_t[sliceDimension] remSizes = _sizes[i.length .. $];
	auto basePortion = _slice[index .. index + _indexer[i.length - 1]];
 	return Mat!(T, sliceDimension)(basePortion, remSizes);
      }
  }
  static if (dimension == 2)
    {
      auto identity()
      {
	debug assert(dim(0) == dim(1));
	auto n = dim(0);
	auto id = Mat!(T, 2)([n, n]);
	foreach(k; 0 .. n)
	  id[k, k] = T(1);
	return id;
      }
      bool canMultiply(Mat!(T, 2) b)
      {
	return this.dim(1) == b.dim(0);
      }
      auto opBinary(string op)(Mat!(T, 2) b)
	if (op == "*")
	  {
	    debug assert(canMultiply(b));
	    auto res = Mat!(T, 2)([this.dim(0), b.dim(1)]);
	    foreach(i; 0 .. res.dim(0))
	      foreach(k; 0 .. this.dim(1))
		foreach(j; 0 .. res.dim(1))
		  res[i, j] = res[i, j] + this[i, k] * b[k, j];
	    return res;
	  }
      auto opBinary(string op)(ulong exp)
	if (op == "^^")
	  {
	    return this.pow(identity, exp);
	  }
      mixin interiorBinPow;
    }
}

struct Mod(T, ulong mod)
{
  alias This = Mod!(T, mod);
  T _rep; T rep() {return _rep;}
  static auto fromPositive(T t)
  {
    pragma(inline, true);
    return Mod!(T, mod)(t % mod);
  }
  static auto fromNegative(T t)
  {
    pragma(inline, true);
    return Mod!(T, mod)(t % mod + mod);
  }
  string toString()
  {
    return to!string(rep);
  }
  debug invariant
  {
    assert(_rep >= 0 && _rep < mod);
  }
  auto opBinary(string op)(This b)
  {
    static if (op == "+")
      {
	T resrep = _rep + b._rep;
	if (resrep >= mod) resrep -= mod;
	return This(resrep);
      }
    else static if (op == "-")
      {
	T resrep = _rep - b._rep;
	if (resrep < 0) resrep += mod;
	return This(resrep);
      }
    else static if (op == "*")
      {
	return This.fromPositive(_rep * b._rep);
      }
  }
  auto opBinary(string op)(ulong exp)
       if (op == "^^")
	 {
	   return pow(This(1), exp);
	 }
  mixin interiorBinPow;
}

mixin template interiorBinPow()
{
  alias ThisType = typeof(this);
  auto pow(ThisType res, ulong exp)
    {
      if (exp < 0) debug assert(0);
      auto pow = this;
      while(exp)
	{
	  if (exp & 1)
	    res = res * pow;
	  pow = pow * pow;
	  exp >>= 1;
	}
      return res;
    }
}

// INPUT
File inputFile;
DList!string _words;
void _wordsFill()
{
  while (_words.empty) _words.insertBack(inputFile.readln.split);
}
string popWord()
{
  _wordsFill;
  auto word = _words.front;
  _words.removeFront;
  return word;
}
string peekWord()
{
  _wordsFill;
  return _words.front;
}
T next(T)()
{
  return to!T(popWord);
}
T peek(T)()
{
  return to!T(peekWord);
}
auto next(T, S...)(S s)
{
  static if (S.length == 0)
    {
      return to!T(popWord);
    }
  else
    {
      auto res = new typeof(next!T(s[1 .. $]))[](cast(size_t)s[0]);
      foreach(ref elem; res)
        elem = next!T(s[1 .. $]);
      return res;
    }
}

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

enum mod = 998244353;
alias M = Mod!(long, mod);
M[300_000 + 1] prefact;
M noSubsets(int n, int k)
{
  if (n == 0) return M(0);
  if (k > n || k < 0) return M(0);
  // k <= n && k >= 0
  return prefact[n] * (prefact[n - k] * prefact[k])^^(mod - 2);
}

void main(string[] args)
{
  inputFile = stdin;
  prefact[0] = M(1);
  foreach(i; 1 .. prefact.length)
    prefact[i] = M(i) * prefact[i - 1];
  auto events = new Tuple!(int, int, int)[](0);
  auto n = next!int;
  auto k = next!int;
  foreach(seg; 0 .. n)
    {
      auto l = next!int;
      auto r = next!int;
      events ~= tuple(l, -1, seg);
      events ~= tuple(r, +1, seg);
    }
  auto sevents = sort(events);
  int cnt = 0;
  M res = M(0);
  foreach(event; sevents)
    {
      cnt -= event[1];
      if (event[1] == -1)
	{
	  res = res + (noSubsets(cnt, k) - noSubsets(cnt - 1, k));
	}
    }
  res.writeln;
}
ulong bitCnt(long x)
{
  ulong cnt = 0;
  while(x) {cnt += x & 1; x>>=1;}
  return cnt;
}
alias Arr(T) = Mat!(T, 1);
struct Mat(T, size_t dimension)
{
  T[] _baseArray;
  T[] _slice;
  size_t[dimension] _sizes; size_t dim(size_t i) {return _sizes[i];}
  size_t[dimension] _indexer;
  this(T[] baseArray, size_t[dimension] sizes)
  {
    _baseArray = baseArray;
    _sizes = sizes;
    _indexer[dimension - 1] = 1;
    static foreach_reverse(i; 0 .. dimension - 1)
      _indexer[i] = _indexer[i + 1] * _sizes[i + 1];
    auto requiredSize = _indexer[0] * _sizes[0];
    debug assert(_baseArray.length >= requiredSize);
    _slice = _baseArray[0 .. requiredSize];
  }
  this(size_t[dimension] sizes)
  {
    size_t reqSize = 1;
    static foreach(i; 0 .. dimension)
      reqSize *= sizes[i];
    this(new T[](reqSize), sizes);
  }
  ref auto opIndex()
  {
    pragma(inline, true);
    return _slice[];
  }
  ref auto opIndex(I...)(I i)
  {
    pragma(inline, true);
    debug assert(i.length <= dimension);
    size_t index = mixin(iota(0, i.length).map!(j => text("i[", j, "]*_indexer[", j, "]")).join("+"));
    static if (i.length == dimension)
      {
	return _slice[index];
      }
    else
      {
	enum sliceDimension = dimension - i.length;
	size_t[sliceDimension] remSizes = _sizes[i.length .. $];
	auto basePortion = _slice[index .. index + _indexer[i.length - 1]];
 	return Mat!(T, sliceDimension)(basePortion, remSizes);
      }
  }
  static if (dimension == 2)
    {
      auto identity()
      {
	debug assert(dim(0) == dim(1));
	auto n = dim(0);
	auto id = Mat!(T, 2)([n, n]);
	foreach(k; 0 .. n)
	  id[k, k] = T(1);
	return id;
      }
      bool canMultiply(Mat!(T, 2) b)
      {
	return this.dim(1) == b.dim(0);
      }
      auto opBinary(string op)(Mat!(T, 2) b)
	if (op == "*")
	  {
	    debug assert(canMultiply(b));
	    auto res = Mat!(T, 2)([this.dim(0), b.dim(1)]);
	    foreach(i; 0 .. res.dim(0))
	      foreach(k; 0 .. this.dim(1))
		foreach(j; 0 .. res.dim(1))
		  res[i, j] = res[i, j] + this[i, k] * b[k, j];
	    return res;
	  }
      auto opBinary(string op)(ulong exp)
	if (op == "^^")
	  {
	    return this.pow(identity, exp);
	  }
      mixin interiorBinPow;
    }
}

struct Mod(T, ulong mod)
{
  alias This = Mod!(T, mod);
  T _rep; T rep() {return _rep;}
  static auto fromPositive(T t)
  {
    pragma(inline, true);
    return Mod!(T, mod)(t % mod);
  }
  static auto fromNegative(T t)
  {
    pragma(inline, true);
    return Mod!(T, mod)(t % mod + mod);
  }
  string toString()
  {
    return to!string(rep);
  }
  debug invariant
  {
    assert(_rep >= 0 && _rep < mod);
  }
  auto opBinary(string op)(This b)
  {
    static if (op == "+")
      {
	T resrep = _rep + b._rep;
	if (resrep >= mod) resrep -= mod;
	return This(resrep);
      }
    else static if (op == "-")
      {
	T resrep = _rep - b._rep;
	if (resrep < 0) resrep += mod;
	return This(resrep);
      }
    else static if (op == "*")
      {
	return This.fromPositive(_rep * b._rep);
      }
  }
  auto opBinary(string op)(ulong exp)
       if (op == "^^")
	 {
	   return pow(This(1), exp);
	 }
  mixin interiorBinPow;
}

mixin template interiorBinPow()
{
  alias ThisType = typeof(this);
  auto pow(ThisType res, ulong exp)
    {
      if (exp < 0) debug assert(0);
      auto pow = this;
      while(exp)
	{
	  if (exp & 1)
	    res = res * pow;
	  pow = pow * pow;
	  exp >>= 1;
	}
      return res;
    }
}

// INPUT
File inputFile;
DList!string _words;
void _wordsFill()
{
  while (_words.empty) _words.insertBack(inputFile.readln.split);
}
string popWord()
{
  _wordsFill;
  auto word = _words.front;
  _words.removeFront;
  return word;
}
string peekWord()
{
  _wordsFill;
  return _words.front;
}
T next(T)()
{
  return to!T(popWord);
}
T peek(T)()
{
  return to!T(peekWord);
}
auto next(T, S...)(S s)
{
  static if (S.length == 0)
    {
      return to!T(popWord);
    }
  else
    {
      auto res = new typeof(next!T(s[1 .. $]))[](cast(size_t)s[0]);
      foreach(ref elem; res)
        elem = next!T(s[1 .. $]);
      return res;
    }
}

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

enum mod = 998244353;
alias M = Mod!(long, mod);
M[300_000 + 1] prefact;
M[300_000 + 1] preInvFact;
M noSubsets(int n, int k)
{
  if (n == 0) return M(0);
  if (k > n || k < 0) return M(0);
  // k <= n && k >= 0
  return prefact[n] * preInvFact[n - k] * preInvFact[k];
}

void main(string[] args)
{
  inputFile = stdin;
  prefact[0] = M(1);
  preInvFact[0] = M(1);
  foreach(i; 1 .. prefact.length)
    {
      prefact[i] = M(i) * prefact[i - 1];
      preInvFact[i] = prefact[i] ^^ (mod - 2);
    }
  auto events = new Tuple!(int, int, int)[](0);
  auto n = next!int;
  auto k = next!int;
  foreach(seg; 0 .. n)
    {
      auto l = next!int;
      auto r = next!int;
      events ~= tuple(l, -1, seg);
      events ~= tuple(r, +1, seg);
    }
  auto sevents = sort(events);
  int cnt = 0;
  M res = M(0);
  foreach(event; sevents)
    {
      cnt -= event[1];
      if (event[1] == -1)
	{
	  res = res + (noSubsets(cnt, k) - noSubsets(cnt - 1, k));
	}
    }
  res.writeln;
}
ulong bitCnt(long x)
{
  ulong cnt = 0;
  while(x) {cnt += x & 1; x>>=1;}
  return cnt;
}
alias Arr(T) = Mat!(T, 1);
struct Mat(T, size_t dimension)
{
  T[] _baseArray;
  T[] _slice;
  size_t[dimension] _sizes; size_t dim(size_t i) {return _sizes[i];}
  size_t[dimension] _indexer;
  this(T[] baseArray, size_t[dimension] sizes)
  {
    _baseArray = baseArray;
    _sizes = sizes;
    _indexer[dimension - 1] = 1;
    static foreach_reverse(i; 0 .. dimension - 1)
      _indexer[i] = _indexer[i + 1] * _sizes[i + 1];
    auto requiredSize = _indexer[0] * _sizes[0];
    debug assert(_baseArray.length >= requiredSize);
    _slice = _baseArray[0 .. requiredSize];
  }
  this(size_t[dimension] sizes)
  {
    size_t reqSize = 1;
    static foreach(i; 0 .. dimension)
      reqSize *= sizes[i];
    this(new T[](reqSize), sizes);
  }
  ref auto opIndex()
  {
    pragma(inline, true);
    return _slice[];
  }
  ref auto opIndex(I...)(I i)
  {
    pragma(inline, true);
    debug assert(i.length <= dimension);
    size_t index = mixin(iota(0, i.length).map!(j => text("i[", j, "]*_indexer[", j, "]")).join("+"));
    static if (i.length == dimension)
      {
	return _slice[index];
      }
    else
      {
	enum sliceDimension = dimension - i.length;
	size_t[sliceDimension] remSizes = _sizes[i.length .. $];
	auto basePortion = _slice[index .. index + _indexer[i.length - 1]];
 	return Mat!(T, sliceDimension)(basePortion, remSizes);
      }
  }
  static if (dimension == 2)
    {
      auto identity()
      {
	debug assert(dim(0) == dim(1));
	auto n = dim(0);
	auto id = Mat!(T, 2)([n, n]);
	foreach(k; 0 .. n)
	  id[k, k] = T(1);
	return id;
      }
      bool canMultiply(Mat!(T, 2) b)
      {
	return this.dim(1) == b.dim(0);
      }
      auto opBinary(string op)(Mat!(T, 2) b)
	if (op == "*")
	  {
	    debug assert(canMultiply(b));
	    auto res = Mat!(T, 2)([this.dim(0), b.dim(1)]);
	    foreach(i; 0 .. res.dim(0))
	      foreach(k; 0 .. this.dim(1))
		foreach(j; 0 .. res.dim(1))
		  res[i, j] = res[i, j] + this[i, k] * b[k, j];
	    return res;
	  }
      auto opBinary(string op)(ulong exp)
	if (op == "^^")
	  {
	    return this.pow(identity, exp);
	  }
      mixin interiorBinPow;
    }
}

struct Mod(T, ulong mod)
{
  alias This = Mod!(T, mod);
  T _rep; T rep() {return _rep;}
  static auto fromPositive(T t)
  {
    pragma(inline, true);
    return Mod!(T, mod)(t % mod);
  }
  static auto fromNegative(T t)
  {
    pragma(inline, true);
    return Mod!(T, mod)(t % mod + mod);
  }
  string toString()
  {
    return to!string(rep);
  }
  debug invariant
  {
    assert(_rep >= 0 && _rep < mod);
  }
  auto opBinary(string op)(This b)
  {
    static if (op == "+")
      {
	T resrep = _rep + b._rep;
	if (resrep >= mod) resrep -= mod;
	return This(resrep);
      }
    else static if (op == "-")
      {
	T resrep = _rep - b._rep;
	if (resrep < 0) resrep += mod;
	return This(resrep);
      }
    else static if (op == "*")
      {
	return This.fromPositive(_rep * b._rep);
      }
  }
  auto opBinary(string op)(ulong exp)
       if (op == "^^")
	 {
	   return pow(This(1), exp);
	 }
  mixin interiorBinPow;
}

mixin template interiorBinPow()
{
  alias ThisType = typeof(this);
  auto pow(ThisType res, ulong exp)
    {
      if (exp < 0) debug assert(0);
      auto pow = this;
      while(exp)
	{
	  if (exp & 1)
	    res = res * pow;
	  pow = pow * pow;
	  exp >>= 1;
	}
      return res;
    }
}

// INPUT
File inputFile;
DList!string _words;
void _wordsFill()
{
  while (_words.empty) _words.insertBack(inputFile.readln.split);
}
string popWord()
{
  _wordsFill;
  auto word = _words.front;
  _words.removeFront;
  return word;
}
string peekWord()
{
  _wordsFill;
  return _words.front;
}
T next(T)()
{
  return to!T(popWord);
}
T peek(T)()
{
  return to!T(peekWord);
}
auto next(T, S...)(S s)
{
  static if (S.length == 0)
    {
      return to!T(popWord);
    }
  else
    {
      auto res = new typeof(next!T(s[1 .. $]))[](cast(size_t)s[0]);
      foreach(ref elem; res)
        elem = next!T(s[1 .. $]);
      return res;
    }
}

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

enum mod = 998244353;
alias M = Mod!(long, mod);
M[300_000 + 1] prefact;
M[300_000 + 1] preInvFact;
M[300_000 + 1] preNoSubsets;
M noSubsets(int n, int k)
{
  if (n == 0) return M(0);
  if (k > n || k < 0) return M(0);
  // k <= n && k >= 0
  return prefact[n] * preInvFact[n - k] * preInvFact[k];
}

void main(string[] args)
{
  inputFile = stdin;
  prefact[0] = M(1);
  preInvFact[0] = M(1);
  foreach(i; 1 .. prefact.length)
    {
      prefact[i] = M(i) * prefact[i - 1];
      preInvFact[i] = prefact[i] ^^ (mod - 2);
    }

  auto n = next!int;
  auto k = next!int;
  auto events = new Tuple!(int, int)[](2 * n);
  foreach(i; 0 .. n + 1)
    preNoSubsets[i] = noSubsets(i, k);
  M[300_000 + 1] preDelta;
  preDelta[0] = preNoSubsets[0];
  foreach(i; 1 .. n + 1)
    preDelta[i] = preNoSubsets[i] - preNoSubsets[i - 1];
  foreach(seg; 0 .. n)
    {
      auto l = next!int;
      auto r = next!int;
      events[2 * seg] = tuple(l, -1);
      events[2 * seg + 1] = tuple(r, +1);
    }
  auto sevents = sort(events);
  int cnt = 0;
  M res = M(0);
  foreach(event; sevents)
    {
      cnt -= event[1];
      if (event[1] == -1)
	{
	  res = res + preDelta[cnt];
	}
    }
  res.writeln;
}
ulong bitCnt(long x)
{
  ulong cnt = 0;
  while(x) {cnt += x & 1; x>>=1;}
  return cnt;
}
alias Arr(T) = Mat!(T, 1);
struct Mat(T, size_t dimension)
{
  T[] _baseArray;
  T[] _slice;
  size_t[dimension] _sizes; size_t dim(size_t i) {return _sizes[i];}
  size_t[dimension] _indexer;
  this(T[] baseArray, size_t[dimension] sizes)
  {
    _baseArray = baseArray;
    _sizes = sizes;
    _indexer[dimension - 1] = 1;
    static foreach_reverse(i; 0 .. dimension - 1)
      _indexer[i] = _indexer[i + 1] * _sizes[i + 1];
    auto requiredSize = _indexer[0] * _sizes[0];
    debug assert(_baseArray.length >= requiredSize);
    _slice = _baseArray[0 .. requiredSize];
  }
  this(size_t[dimension] sizes)
  {
    size_t reqSize = 1;
    static foreach(i; 0 .. dimension)
      reqSize *= sizes[i];
    this(new T[](reqSize), sizes);
  }
  ref auto opIndex()
  {
    pragma(inline, true);
    return _slice[];
  }
  ref auto opIndex(I...)(I i)
  {
    pragma(inline, true);
    debug assert(i.length <= dimension);
    size_t index = mixin(iota(0, i.length).map!(j => text("i[", j, "]*_indexer[", j, "]")).join("+"));
    static if (i.length == dimension)
      {
	return _slice[index];
      }
    else
      {
	enum sliceDimension = dimension - i.length;
	size_t[sliceDimension] remSizes = _sizes[i.length .. $];
	auto basePortion = _slice[index .. index + _indexer[i.length - 1]];
 	return Mat!(T, sliceDimension)(basePortion, remSizes);
      }
  }
  static if (dimension == 2)
    {
      auto identity()
      {
	debug assert(dim(0) == dim(1));
	auto n = dim(0);
	auto id = Mat!(T, 2)([n, n]);
	foreach(k; 0 .. n)
	  id[k, k] = T(1);
	return id;
      }
      bool canMultiply(Mat!(T, 2) b)
      {
	return this.dim(1) == b.dim(0);
      }
      auto opBinary(string op)(Mat!(T, 2) b)
	if (op == "*")
	  {
	    debug assert(canMultiply(b));
	    auto res = Mat!(T, 2)([this.dim(0), b.dim(1)]);
	    foreach(i; 0 .. res.dim(0))
	      foreach(k; 0 .. this.dim(1))
		foreach(j; 0 .. res.dim(1))
		  res[i, j] = res[i, j] + this[i, k] * b[k, j];
	    return res;
	  }
      auto opBinary(string op)(ulong exp)
	if (op == "^^")
	  {
	    return this.pow(identity, exp);
	  }
      mixin interiorBinPow;
    }
}

struct Mod(T, ulong mod)
{
  alias This = Mod!(T, mod);
  T _rep; T rep() {return _rep;}
  static auto fromPositive(T t)
  {
    pragma(inline, true);
    return Mod!(T, mod)(t % mod);
  }
  static auto fromNegative(T t)
  {
    pragma(inline, true);
    return Mod!(T, mod)(t % mod + mod);
  }
  string toString()
  {
    return to!string(rep);
  }
  debug invariant
  {
    assert(_rep >= 0 && _rep < mod);
  }
  auto opBinary(string op)(This b)
  {
    static if (op == "+")
      {
	T resrep = _rep + b._rep;
	if (resrep >= mod) resrep -= mod;
	return This(resrep);
      }
    else static if (op == "-")
      {
	T resrep = _rep - b._rep;
	if (resrep < 0) resrep += mod;
	return This(resrep);
      }
    else static if (op == "*")
      {
	return This.fromPositive(_rep * b._rep);
      }
  }
  auto opBinary(string op)(ulong exp)
       if (op == "^^")
	 {
	   return pow(This(1), exp);
	 }
  mixin interiorBinPow;
}

mixin template interiorBinPow()
{
  alias ThisType = typeof(this);
  auto pow(ThisType res, ulong exp)
    {
      if (exp < 0) debug assert(0);
      auto pow = this;
      while(exp)
	{
	  if (exp & 1)
	    res = res * pow;
	  pow = pow * pow;
	  exp >>= 1;
	}
      return res;
    }
}

// INPUT
File inputFile;
DList!string _words;
void _wordsFill()
{
  while (_words.empty) _words.insertBack(inputFile.readln.split);
}
string popWord()
{
  _wordsFill;
  auto word = _words.front;
  _words.removeFront;
  return word;
}
string peekWord()
{
  _wordsFill;
  return _words.front;
}
T next(T)()
{
  return to!T(popWord);
}
T peek(T)()
{
  return to!T(peekWord);
}
auto next(T, S...)(S s)
{
  static if (S.length == 0)
    {
      return to!T(popWord);
    }
  else
    {
      auto res = new typeof(next!T(s[1 .. $]))[](cast(size_t)s[0]);
      foreach(ref elem; res)
        elem = next!T(s[1 .. $]);
      return res;
    }
}

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

enum mod = 998244353;
alias M = Mod!(long, mod);
M[300_000 + 1] prefact;
M[300_000 + 1] preInvFact;
M[300_000 + 1] preNoSubsets;
M noSubsets(int n, int k)
{
  if (n == 0) return M(0);
  if (k > n || k < 0) return M(0);
  // k <= n && k >= 0
  return prefact[n] * preInvFact[n - k] * preInvFact[k];
}

void main(string[] args)
{
  inputFile = stdin;
  prefact[0] = M(1);
  preInvFact[0] = M(1);
  foreach(i; 1 .. prefact.length)
    {
      prefact[i] = M(i) * prefact[i - 1];
      preInvFact[i] = prefact[i] ^^ (mod - 2);
    }

  auto n = next!int;
  auto k = next!int;
  auto events = new Tuple!(int, int)[](2 * n);
  foreach(i; 0 .. n + 1)
    preNoSubsets[i] = noSubsets(i, k);
  foreach(seg; 0 .. n)
    {
      auto l = next!int;
      auto r = next!int;
      events[2 * seg] = tuple(l, -1);
      events[2 * seg + 1] = tuple(r, +1);
    }
  auto sevents = sort(events);
  int cnt = 0;
  M res = M(0);
  foreach(event; sevents)
    {
      cnt -= event[1];
      if (event[1] == -1)
	{
	  res = res + preNoSubsets[cnt];
	  if (cnt != 0)
	    res = res - preNoSubsets[cnt - 1];
	}
    }
  res.writeln;
}
ulong bitCnt(long x)
{
  ulong cnt = 0;
  while(x) {cnt += x & 1; x>>=1;}
  return cnt;
}
alias Arr(T) = Mat!(T, 1);
struct Mat(T, size_t dimension)
{
  T[] _baseArray;
  T[] _slice;
  size_t[dimension] _sizes; size_t dim(size_t i) {return _sizes[i];}
  size_t[dimension] _indexer;
  this(T[] baseArray, size_t[dimension] sizes)
  {
    _baseArray = baseArray;
    _sizes = sizes;
    _indexer[dimension - 1] = 1;
    static foreach_reverse(i; 0 .. dimension - 1)
      _indexer[i] = _indexer[i + 1] * _sizes[i + 1];
    auto requiredSize = _indexer[0] * _sizes[0];
    debug assert(_baseArray.length >= requiredSize);
    _slice = _baseArray[0 .. requiredSize];
  }
  this(size_t[dimension] sizes)
  {
    size_t reqSize = 1;
    static foreach(i; 0 .. dimension)
      reqSize *= sizes[i];
    this(new T[](reqSize), sizes);
  }
  ref auto opIndex()
  {
    pragma(inline, true);
    return _slice[];
  }
  ref auto opIndex(I...)(I i)
  {
    pragma(inline, true);
    debug assert(i.length <= dimension);
    size_t index = mixin(iota(0, i.length).map!(j => text("i[", j, "]*_indexer[", j, "]")).join("+"));
    static if (i.length == dimension)
      {
	return _slice[index];
      }
    else
      {
	enum sliceDimension = dimension - i.length;
	size_t[sliceDimension] remSizes = _sizes[i.length .. $];
	auto basePortion = _slice[index .. index + _indexer[i.length - 1]];
 	return Mat!(T, sliceDimension)(basePortion, remSizes);
      }
  }
  static if (dimension == 2)
    {
      auto identity()
      {
	debug assert(dim(0) == dim(1));
	auto n = dim(0);
	auto id = Mat!(T, 2)([n, n]);
	foreach(k; 0 .. n)
	  id[k, k] = T(1);
	return id;
      }
      bool canMultiply(Mat!(T, 2) b)
      {
	return this.dim(1) == b.dim(0);
      }
      auto opBinary(string op)(Mat!(T, 2) b)
	if (op == "*")
	  {
	    debug assert(canMultiply(b));
	    auto res = Mat!(T, 2)([this.dim(0), b.dim(1)]);
	    foreach(i; 0 .. res.dim(0))
	      foreach(k; 0 .. this.dim(1))
		foreach(j; 0 .. res.dim(1))
		  res[i, j] = res[i, j] + this[i, k] * b[k, j];
	    return res;
	  }
      auto opBinary(string op)(ulong exp)
	if (op == "^^")
	  {
	    return this.pow(identity, exp);
	  }
      mixin interiorBinPow;
    }
}

struct Mod(T, ulong mod)
{
  alias This = Mod!(T, mod);
  T _rep; T rep() {return _rep;}
  static auto fromPositive(T t)
  {
    pragma(inline, true);
    return Mod!(T, mod)(t % mod);
  }
  static auto fromNegative(T t)
  {
    pragma(inline, true);
    return Mod!(T, mod)(t % mod + mod);
  }
  string toString()
  {
    return to!string(rep);
  }
  debug invariant
  {
    assert(_rep >= 0 && _rep < mod);
  }
  auto opBinary(string op)(This b)
  {
    static if (op == "+")
      {
	T resrep = _rep + b._rep;
	if (resrep >= mod) resrep -= mod;
	return This(resrep);
      }
    else static if (op == "-")
      {
	T resrep = _rep - b._rep;
	if (resrep < 0) resrep += mod;
	return This(resrep);
      }
    else static if (op == "*")
      {
	return This.fromPositive(_rep * b._rep);
      }
  }
  auto opBinary(string op)(ulong exp)
       if (op == "^^")
	 {
	   return pow(This(1), exp);
	 }
  mixin interiorBinPow;
}

mixin template interiorBinPow()
{
  alias ThisType = typeof(this);
  auto pow(ThisType res, ulong exp)
    {
      if (exp < 0) debug assert(0);
      auto pow = this;
      while(exp)
	{
	  if (exp & 1)
	    res = res * pow;
	  pow = pow * pow;
	  exp >>= 1;
	}
      return res;
    }
}

// INPUT
File inputFile;
DList!string _words;
void _wordsFill()
{
  while (_words.empty) _words.insertBack(inputFile.readln.split);
}
string popWord()
{
  _wordsFill;
  auto word = _words.front;
  _words.removeFront;
  return word;
}
string peekWord()
{
  _wordsFill;
  return _words.front;
}
T next(T)()
{
  return to!T(popWord);
}
T peek(T)()
{
  return to!T(peekWord);
}
auto next(T, S...)(S s)
{
  static if (S.length == 0)
    {
      return to!T(popWord);
    }
  else
    {
      auto res = new typeof(next!T(s[1 .. $]))[](cast(size_t)s[0]);
      foreach(ref elem; res)
        elem = next!T(s[1 .. $]);
      return res;
    }
}

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

enum mod = 998244353;
alias M = Mod!(long, mod);
M[300_000 + 1] prefact;
M[300_000 + 1] preInvFact;
M[300_000 + 1] preNoSubsets;
M noSubsets(int n, int k)
{
  if (n == 0) return M(0);
  if (k > n || k < 0) return M(0);
  // k <= n && k >= 0
  return prefact[n] * preInvFact[n - k] * preInvFact[k];
}

void main(string[] args)
{
  inputFile = stdin;
  prefact[0] = M(1);
  preInvFact[0] = M(1);
  foreach(i; 1 .. prefact.length)
    {
      prefact[i] = M(i) * prefact[i - 1];
      preInvFact[i] = prefact[i] ^^ (mod - 2);
    }

  auto n = next!int;
  auto k = next!int;
  auto events = new Tuple!(int, int)[](2 * n);
  foreach(i; 0 .. n + 1)
    preNoSubsets[i] = noSubsets(i, k);
  foreach(seg; 0 .. n)
    {
      auto l = next!int;
      auto r = next!int;
      events[2 * seg] = tuple(l, -1);
      events[2 * seg + 1] = tuple(r, +1);
    }
  auto sevents = sort(events);
  int cnt = 0;
  M res = M(0);
  foreach(event; sevents)
    {
      cnt -= event[1];
      if (event[1] == -1)
	{
	  res += preNoSubsets[cnt];
	  if (cnt != 0)
	    res -= preNoSubsets[cnt - 1];
	}
    }
  res.writeln;
}
ulong bitCnt(long x)
{
  ulong cnt = 0;
  while(x) {cnt += x & 1; x>>=1;}
  return cnt;
}
alias Arr(T) = Mat!(T, 1);
struct Mat(T, size_t dimension)
{
  T[] _baseArray;
  T[] _slice;
  size_t[dimension] _sizes; size_t dim(size_t i) {return _sizes[i];}
  size_t[dimension] _indexer;
  this(T[] baseArray, size_t[dimension] sizes)
  {
    _baseArray = baseArray;
    _sizes = sizes;
    _indexer[dimension - 1] = 1;
    static foreach_reverse(i; 0 .. dimension - 1)
      _indexer[i] = _indexer[i + 1] * _sizes[i + 1];
    auto requiredSize = _indexer[0] * _sizes[0];
    debug assert(_baseArray.length >= requiredSize);
    _slice = _baseArray[0 .. requiredSize];
  }
  this(size_t[dimension] sizes)
  {
    size_t reqSize = 1;
    static foreach(i; 0 .. dimension)
      reqSize *= sizes[i];
    this(new T[](reqSize), sizes);
  }
  ref auto opIndex()
  {
    pragma(inline, true);
    return _slice[];
  }
  ref auto opIndex(I...)(I i)
  {
    pragma(inline, true);
    debug assert(i.length <= dimension);
    size_t index = mixin(iota(0, i.length).map!(j => text("i[", j, "]*_indexer[", j, "]")).join("+"));
    static if (i.length == dimension)
      {
	return _slice[index];
      }
    else
      {
	enum sliceDimension = dimension - i.length;
	size_t[sliceDimension] remSizes = _sizes[i.length .. $];
	auto basePortion = _slice[index .. index + _indexer[i.length - 1]];
 	return Mat!(T, sliceDimension)(basePortion, remSizes);
      }
  }
  static if (dimension == 2)
    {
      auto identity()
      {
	debug assert(dim(0) == dim(1));
	auto n = dim(0);
	auto id = Mat!(T, 2)([n, n]);
	foreach(k; 0 .. n)
	  id[k, k] = T(1);
	return id;
      }
      bool canMultiply(Mat!(T, 2) b)
      {
	return this.dim(1) == b.dim(0);
      }
      auto opBinary(string op)(Mat!(T, 2) b)
	if (op == "*")
	  {
	    debug assert(canMultiply(b));
	    auto res = Mat!(T, 2)([this.dim(0), b.dim(1)]);
	    foreach(i; 0 .. res.dim(0))
	      foreach(k; 0 .. this.dim(1))
		foreach(j; 0 .. res.dim(1))
		  res[i, j] = res[i, j] + this[i, k] * b[k, j];
	    return res;
	  }
      auto opBinary(string op)(ulong exp)
	if (op == "^^")
	  {
	    return this.pow(identity, exp);
	  }
      mixin interiorBinPow;
    }
}

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

mixin template interiorBinPow()
{
  alias ThisType = typeof(this);
  auto pow(ThisType res, ulong exp)
    {
      if (exp < 0) debug assert(0);
      auto pow = this;
      while(exp)
	{
	  if (exp & 1)
	    res *= pow;
	  pow *= pow;
	  exp >>= 1;
	}
      return res;
    }
}

// INPUT
File inputFile;
DList!string _words;
void _wordsFill()
{
  while (_words.empty) _words.insertBack(inputFile.readln.split);
}
string popWord()
{
  _wordsFill;
  auto word = _words.front;
  _words.removeFront;
  return word;
}
string peekWord()
{
  _wordsFill;
  return _words.front;
}
T next(T)()
{
  return to!T(popWord);
}
T peek(T)()
{
  return to!T(peekWord);
}
auto next(T, S...)(S s)
{
  static if (S.length == 0)
    {
      return to!T(popWord);
    }
  else
    {
      auto res = new typeof(next!T(s[1 .. $]))[](cast(size_t)s[0]);
      foreach(ref elem; res)
        elem = next!T(s[1 .. $]);
      return res;
    }
}

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

enum mod = 998244353;
alias M = Mod!(long, mod);
M[300_000 + 1] prefact;
M[300_000 + 1] preInvFact;
M[300_000 + 1] preNoSubsets;
M noSubsets(int n, int k)
{
  if (n == 0) return M(0);
  if (k > n || k < 0) return M(0);
  // k <= n && k >= 0
  return prefact[n] * preInvFact[n - k] * preInvFact[k];
}

void main(string[] args)
{
  inputFile = stdin;
  prefact[0] = M(1);
  preInvFact[0] = M(1);
  foreach(i; 1 .. prefact.length)
    {
      prefact[i] = M(i) * prefact[i - 1];
      preInvFact[i] = prefact[i] ^^ (mod - 2);
    }
  auto events = new Tuple!(int, int)[](0);
  auto n = next!int;
  auto k = next!int;
  foreach(i; 0 .. n + 1)
    preNoSubsets[i] = noSubsets(i, k);
  foreach(seg; 0 .. n)
    {
      auto l = next!int;
      auto r = next!int;
      events ~= tuple(l, -1);
      events ~= tuple(r, +1);
    }
  auto sevents = sort(events);
  int cnt = 0;
  M res = M(0);
  foreach(event; sevents)
    {
      cnt -= event[1];
      if (event[1] == -1)
	{
	  res = res + preNoSubsets[cnt];
	  if (cnt != 0)
	    res = res - preNoSubsets[cnt - 1];
	}
    }
  res.writeln;
}
ulong bitCnt(long x)
{
  ulong cnt = 0;
  while(x) {cnt += x & 1; x>>=1;}
  return cnt;
}
alias Arr(T) = Mat!(T, 1);
struct Mat(T, size_t dimension)
{
  T[] _baseArray;
  T[] _slice;
  size_t[dimension] _sizes; size_t dim(size_t i) {return _sizes[i];}
  size_t[dimension] _indexer;
  this(T[] baseArray, size_t[dimension] sizes)
  {
    _baseArray = baseArray;
    _sizes = sizes;
    _indexer[dimension - 1] = 1;
    static foreach_reverse(i; 0 .. dimension - 1)
      _indexer[i] = _indexer[i + 1] * _sizes[i + 1];
    auto requiredSize = _indexer[0] * _sizes[0];
    debug assert(_baseArray.length >= requiredSize);
    _slice = _baseArray[0 .. requiredSize];
  }
  this(size_t[dimension] sizes)
  {
    size_t reqSize = 1;
    static foreach(i; 0 .. dimension)
      reqSize *= sizes[i];
    this(new T[](reqSize), sizes);
  }
  ref auto opIndex()
  {
    pragma(inline, true);
    return _slice[];
  }
  ref auto opIndex(I...)(I i)
  {
    pragma(inline, true);
    debug assert(i.length <= dimension);
    size_t index = mixin(iota(0, i.length).map!(j => text("i[", j, "]*_indexer[", j, "]")).join("+"));
    static if (i.length == dimension)
      {
	return _slice[index];
      }
    else
      {
	enum sliceDimension = dimension - i.length;
	size_t[sliceDimension] remSizes = _sizes[i.length .. $];
	auto basePortion = _slice[index .. index + _indexer[i.length - 1]];
 	return Mat!(T, sliceDimension)(basePortion, remSizes);
      }
  }
  static if (dimension == 2)
    {
      auto identity()
      {
	debug assert(dim(0) == dim(1));
	auto n = dim(0);
	auto id = Mat!(T, 2)([n, n]);
	foreach(k; 0 .. n)
	  id[k, k] = T(1);
	return id;
      }
      bool canMultiply(Mat!(T, 2) b)
      {
	return this.dim(1) == b.dim(0);
      }
      auto opBinary(string op)(Mat!(T, 2) b)
	if (op == "*")
	  {
	    debug assert(canMultiply(b));
	    auto res = Mat!(T, 2)([this.dim(0), b.dim(1)]);
	    foreach(i; 0 .. res.dim(0))
	      foreach(k; 0 .. this.dim(1))
		foreach(j; 0 .. res.dim(1))
		  res[i, j] = res[i, j] + this[i, k] * b[k, j];
	    return res;
	  }
      auto opBinary(string op)(ulong exp)
	if (op == "^^")
	  {
	    return this.pow(identity, exp);
	  }
      mixin interiorBinPow;
    }
}

struct Mod(T, ulong mod)
{
  alias This = Mod!(T, mod);
  T _rep; T rep() {return _rep;}
  static auto fromPositive(T t)
  {
    pragma(inline, true);
    return Mod!(T, mod)(t % mod);
  }
  static auto fromNegative(T t)
  {
    pragma(inline, true);
    return Mod!(T, mod)(t % mod + mod);
  }
  string toString()
  {
    return to!string(rep);
  }
  debug invariant
  {
    assert(_rep >= 0 && _rep < mod);
  }
  auto opBinary(string op)(This b)
  {
    static if (op == "+")
      {
	T resrep = _rep + b._rep;
	if (resrep >= mod) resrep -= mod;
	return This(resrep);
      }
    else static if (op == "-")
      {
	T resrep = _rep - b._rep;
	if (resrep < 0) resrep += mod;
	return This(resrep);
      }
    else static if (op == "*")
      {
	return This.fromPositive(_rep * b._rep);
      }
  }
  auto opBinary(string op)(ulong exp)
       if (op == "^^")
	 {
	   return pow(This(1), exp);
	 }
  mixin interiorBinPow;
}

mixin template interiorBinPow()
{
  alias ThisType = typeof(this);
  auto pow(ThisType res, ulong exp)
    {
      if (exp < 0) debug assert(0);
      auto pow = this;
      while(exp)
	{
	  if (exp & 1)
	    res = res * pow;
	  pow = pow * pow;
	  exp >>= 1;
	}
      return res;
    }
}

// INPUT
File inputFile;
DList!string _words;
void _wordsFill()
{
  while (_words.empty) _words.insertBack(inputFile.readln.split);
}
string popWord()
{
  _wordsFill;
  auto word = _words.front;
  _words.removeFront;
  return word;
}
string peekWord()
{
  _wordsFill;
  return _words.front;
}
T next(T)()
{
  return to!T(popWord);
}
T peek(T)()
{
  return to!T(peekWord);
}
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;
    }
}


Omkar is playing his favorite pixelated video game, Bed Wars! In Bed Wars, there are $$$n$$$ players arranged in a circle, so that for all $$$j$$$ such that $$$2 \leq j \leq n$$$, player $$$j - 1$$$ is to the left of the player $$$j$$$, and player $$$j$$$ is to the right of player $$$j - 1$$$. Additionally, player $$$n$$$ is to the left of player $$$1$$$, and player $$$1$$$ is to the right of player $$$n$$$.Currently, each player is attacking either the player to their left or the player to their right. This means that each player is currently being attacked by either $$$0$$$, $$$1$$$, or $$$2$$$ other players. A key element of Bed Wars strategy is that if a player is being attacked by exactly $$$1$$$ other player, then they should logically attack that player in response. If instead a player is being attacked by $$$0$$$ or $$$2$$$ other players, then Bed Wars strategy says that the player can logically attack either of the adjacent players.Unfortunately, it might be that some players in this game are not following Bed Wars strategy correctly. Omkar is aware of whom each player is currently attacking, and he can talk to any amount of the $$$n$$$ players in the game to make them instead attack another player  — i. e. if they are currently attacking the player to their left, Omkar can convince them to instead attack the player to their right; if they are currently attacking the player to their right, Omkar can convince them to instead attack the player to their left. Omkar would like all players to be acting logically. Calculate the minimum amount of players that Omkar needs to talk to so that after all players he talked to (if any) have changed which player they are attacking, all players are acting logically according to Bed Wars strategy.

Each test contains multiple test cases. The first line contains the number of test cases $$$t$$$ ($$$1 \le t \le 10^4$$$). The descriptions of the test cases follows. The first line of each test case contains one integer $$$n$$$ ($$$3 \leq n \leq 2 \cdot 10^5$$$)  — the amount of players (and therefore beds) in this game of Bed Wars. The second line of each test case contains a string $$$s$$$ of length $$$n$$$. The $$$j$$$-th character of $$$s$$$ is equal to L if the $$$j$$$-th player is attacking the player to their left, and R if the $$$j$$$-th player is attacking the player to their right. It is guaranteed that the sum of $$$n$$$ over all test cases does not exceed $$$2 \cdot 10^5$$$.

For each test case, output one integer: the minimum number of players Omkar needs to talk to to make it so that all players are acting logically according to Bed Wars strategy. It can be proven that it is always possible for Omkar to achieve this under the given constraints.

5
4
RLRL
6
LRRRRL
8
RLLRRRLL
12
LLLLRRLRRRLL
5
RRRRR

NoteIn the first test case, players $$$1$$$ and $$$2$$$ are attacking each other, and players $$$3$$$ and $$$4$$$ are attacking each other. Each player is being attacked by exactly $$$1$$$ other player, and each player is attacking the player that is attacking them, so all players are already being logical according to Bed Wars strategy and Omkar does not need to talk to any of them, making the answer $$$0$$$.In the second test case, not every player acts logically: for example, player $$$3$$$ is attacked only by player $$$2$$$, but doesn't attack him in response. Omkar can talk to player $$$3$$$ to convert the attack arrangement to LRLRRL, in which you can see that all players are being logical according to Bed Wars strategy, making the answer $$$1$$$.

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

void main ()
{
	auto tests = readln.strip.to !(int);
	foreach (test; 0..tests)
	{
		auto n = readln.strip.to !(int);
		auto s = readln.strip.map !(q{a == 'R'}).array;
		auto t = s ~ s ~ s;
		immutable int [] toFind = [0, 1];
		auto pos = t.countUntil (toFind).to !(int);
		if (pos == -1)
		{
			writeln ((n + 2) / 3);
			continue;
		}

		pos += 1;
		writeln (t[pos..pos + n].group.map !(q{(a[1] + 0) / 3}).sum);
	}
}

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

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

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

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

enum INF = 10^^9;

bool isOk(int s, int t, int u) {
  if (s == 0 && u == 0) return (t == 1);
  if (s == 1 && u == 1) return (t == 0);
  return true;
}

void main() {
  try {
    for (; ; ) {
      const numCases = readInt();
      foreach (caseId; 0 .. numCases) {
        const N = readInt();
        const S = readToken();

        int cost(int i, int s) {
          return (S[i] != "LR"[s]) ? 1 : 0;
        }

        int ans = INF;
        foreach (a0; 0 .. 2) foreach (a1; 0 .. 2) {
          auto dp = new int[][][](N + 1, 2, 2);
          foreach (i; 0 .. N + 1) {
            foreach (s; 0 .. 2) foreach (t; 0 .. 2) {
              dp[i][s][t] = INF;
            }
          }
          dp[2][a0][a1] = cost(0, a0) + cost(1, a1);
          foreach (i; 2 .. N) {
            foreach (s; 0 .. 2) foreach (t; 0 .. 2) {
              if (dp[i][s][t] < INF) {
                foreach (u; 0 .. 2) {
                  if (isOk(s, t, u)) {
                    chmin(dp[i + 1][t][u], dp[i][s][t] + cost(i, u));
                  }
                }
              }
            }
          }
          foreach (s; 0 .. 2) foreach (t; 0 .. 2) {
            if (isOk(s, t, a0) && isOk(t, a0, a1)) {
              chmin(ans, dp[N][s][t]);
            }
          }
        }
        writeln(ans);
      }
    }
  } catch (EOFException e) {
  }
}

import std.container;
import std.algorithm;
import std.range;
import std.array;
import std.stdio;
import std.utf;
import std.math;
import std.typecons;

alias type = multi;
struct TestCase
{
  mixin prettyPrinting;

  long n;
  string attacks;

  void solve(long tc = -1)
  {
    auto sol = makeSlice!long(n, 2, 2, 2, 2);
    auto done = makeSlice!bool(n, 2, 2, 2, 2);
    long getSol(long i, byte dir0, byte dirn, byte pdir, byte pset)
    {
      long solution(long val)
      {
        done.at(i).at(dir0).at(dirn).at(pdir).at(pset) = true;
        sol.at(i).at(dir0).at(dirn).at(pdir).at(pset) = val;
        return val;
      }
      if (done.at(i).at(dir0).at(dirn).at(pdir).at(pset))
        return sol.at(i).at(dir0).at(dirn).at(pdir).at(pset);
      long setCost;
      if (pset)
        setCost = attacks.at(i) != 'R';
      else
        setCost = attacks.at(i) != 'L';
      if (i == n - 1)
        {
          if (pset != dirn)
            return solution(long.max);
          if (pdir == 1 && dir0 == 0)
            return solution(setCost);
          if (pdir == 1)
            {
              if (pset != 0)
                return solution(long.max);
              return solution(setCost);
            }
          if (dir0 == 0)
            {
              if (pset != 1)
                return solution(long.max);
              return solution(setCost);
            }
          return solution(setCost);
        }
      assert(i != 0);
      long c0, c1;
      void calc0()
      {
        c0 = getSol(i + 1, dir0, dirn, pset, 0);
        if (c0 != long.max)
          {
            c0 += setCost;
          }
      }
      void calc1()
      {
        c1 = getSol(i + 1, dir0, dirn, pset, 1);
        if (c1 != long.max)
          {
            c1 += setCost;
          }
      }
      if (pdir)
        {
          if (pset)
            {
              calc0();
              return solution(c0);
            }
          calc0(), calc1();
          return solution(min(c0, c1));
        }
      else // pdir = 0
        {
          if (pset)
            {
              calc0(), calc1();
              return solution(min(c0, c1));
            }
          calc1();
          return solution(c1);
        }
    }
    long ans = long.max;
    foreach(dir0; 0 .. long(2))
      foreach(dirn; 0 .. long(2))
        {
          long cost0;
          if (dir0)
            {
              cost0 = attacks.at(0) != 'R';
            }
          else
            {
              cost0 = attacks.at(0) != 'L';
            }
          if (dir0)
            {
              if (dirn)
                {
                  ans = min(ans, cost0 + getSol(1, cast(byte)dir0, cast(byte)dirn, cast(byte)dir0, 0));
                }
              else
                {
                  ans = min(ans, cost0 + getSol(1, cast(byte)dir0, cast(byte)dirn, cast(byte)dir0, 0)
                            , cost0 + getSol(1, cast(byte)dir0, cast(byte)dirn, cast(byte)dir0, 1));
                }
            }
          else
            {
              if (dirn)
                {
                  ans = min(ans, cost0 + getSol(1, cast(byte)dir0, cast(byte)dirn, cast(byte)dir0, 0)
                            , cost0 + getSol(1, cast(byte)dir0, cast(byte)dirn, cast(byte)dir0, 1));
                }
              else
                {
                  ans = min(ans, cost0 + getSol(1, cast(byte)dir0, cast(byte)dirn, cast(byte)dir0, 1));
                }
            }
        }
    writeln(ans);
  }
}

struct Interval
{
  long l, h;

  bool empty()
  {
    return l > h;
  }
}

Interval intersect(Interval a, Interval b)
{
  return Interval(max(a.l, b.l), min(a.h, b.h));
}

struct If
{
  string condition;
}
enum ignore = If("false");
struct Dim
{
  string dimensions;
  int levels;
  this(string dimensions)
  {
    this.dimensions = dimensions;
    levels = cast(int)dimensions.count(",") + 1;
  }
}

template getArrayLevel(W)
{
  static if (isDynamicArray!W && !is(W == string))
    enum getArrayLevel = 1 + getArrayLevel!(removeArray!(W, 1));
  else
    enum getArrayLevel = 0;
}

static foreach(fieldName; 'a' .. cast(char)('z' + 1))
  {
    static if (fieldName != 'o')
      mixin("enum d", fieldName, " = Dim(\"", fieldName, "\");");
  }

mixin template prettyPrinting()
{
  string toString()
  {
    alias structType = typeof(this);
    auto res = appender!(string)();
    res.put(structType.stringof);
    res.put("(");
    static foreach(fieldName; FieldNameTuple!structType)
      {
        res.put(text(" ", fieldName, ": ", mixin(fieldName)));
      }
    res.put(" )");
    res.put("\n");
    return res[];
  }
}

struct Graph(N)
{
  size_t size;
  this(S)(S size)
  {
    adjacencyList.length = cast(size_t) size;
    this.size = cast(size_t) size;
    this.visited = makeSlice!bool(size);
  }
  N[][] adjacencyList;
  alias ne = neighbours;
  N[] neighbours(N n)
  {
    return adjacencyList.at(n);
  }
  alias bcon = biconnect;
  void biconnect(N a, N b)
  {
    adjacencyList.at(a) ~= b;
    adjacencyList.at(b) ~= a;
  }
  alias con = connect;
  void connect(N a, N b)
  {
    adjacencyList.at(a) ~= b;
  }
  void connect(R)(R edges)
  {
    foreach(ref edge; edges)
      {
        connect(edge[0], edge[1]);
      }
  }
  void biconnect(R)(R edges)
  {
    foreach(ref edge; edges)
      {
        biconnect(edge[0], edge[1]);
      }
  }
  alias deg = degree!long;
  auto degree(T)(N a)
  {
    return cast(T) adjacencyList.at(a).length;
  }

  auto visited = new bool[0];
  void dfs(Visitor)(long startNode)
  {
    auto visitor = Visitor.init;
    void internalDfs(long node)
    {
      visited.set(node, true);
      static if (is(typeof({visitor.n = node;})))
        visitor.n = node;
      static if (is(typeof({visitor.pre;})))
        visitor.pre;
      foreach(w; ne(node))
        if (!visited.at(w))
          {
            static if (is(typeof({visitor.w = w;})))
              visitor.w = w;
            static if (is(typeof(visitor.pren)))
              visitor.pren;
            internalDfs(w);
            static if (is(typeof(visitor.postn)))
              visitor.postn;
          }
      static if (is(typeof(visitor.post)))
        visitor.post;
    }
    internalDfs(startNode);
  }
  void dfs(long startNode)
  {
    struct DefVisitor {}
    dfs!DefVisitor(startNode);
  }
}

DList!string _words;

template removeArray(W, int times)
{
  static if (times == 0)
    alias removeArray = W;
  else static if (times == 1)
    alias removeArray = typeof(function(){W w; return w[0];}());
  else
    {
      static assert(isDynamicArray!W);
      alias removeArray = removeArray!(removeArray!(W, 1), times - 1);
    }
}

template baseType(W)
{
  static if (isDynamicArray!W && !is(W == string))
    alias baseType = baseType!(typeof((delegate() {W w; return w[0];})()));
  else
    alias baseType = W;
}

auto makeSlice(E, W, T...)(W size, T otherSizes)
{
  static if (T.length == 0)
    {
      E[] res;
      res.length = cast(size_t) size;
      return res;
    }
  else
    {
      typeof(makeSlice!E(otherSizes))[] res;
      res.length = cast(size_t) size;
      foreach(ref row; res)
        row = makeSlice!E(otherSizes);
      return res;
    }
}

void read(T...)(ref T t)
{
  void basicTypeRead(W)(ref W w)
  {
    import std.stdio: readln;
    while(_words.empty)
      {
        import std.array: split;
        foreach(word; readln.split)
          {
            _words.insertBack(word);
          }
      }
    import std.conv: to;
    string word = _words.front;
    _words.removeFront;
    w = to!W(word);
  }
  void iterableRead(W)(ref W w)
  {
    foreach(ref element; w)
      read(element);
  }
  void tupleRead(W)(ref W w)
  {
    static foreach(j; 0 .. W.length)
      read(w[j]);
  }
  void structRead(W)(ref W readStruct)
  {
    static foreach(fieldName; FieldNameTuple!W)
      {
        with(readStruct)
          {
            alias fieldSymbol = mixin(W.stringof, ".", fieldName);
            alias typeOfField = typeof(mixin(fieldName));
            static if (hasUDA!(fieldSymbol, If))
              enum condition = getUDAs!(fieldSymbol, If)[0].condition;
            else
              enum condition = "true";

            if (mixin(condition))
              {
                static if (hasUDA!(fieldSymbol, Dim))
                  {
                    static assert(isDynamicArray!(typeOfField)
                                  , text(W.stringof, ".", fieldName, " has Dim UDA but isn't a Dynamic Array."));
                    enum uda = getUDAs!(fieldSymbol, Dim)[0];
                    static assert(getArrayLevel!(typeOfField) == uda.levels,
                                  text(W.stringof, ".", fieldName, " has a Dim UDA with different number of dimensions than it's type."));
                    mixin(fieldName) = mixin(q{makeSlice!(baseType!typeOfField)(}, uda.dimensions, q{)});
                  }
                else static if (isDynamicArray!typeOfField && !is(typeOfField == string))
                  {
                    pragma(msg, "Warning: You probably want to add dimension to input ", W.stringof, ".", fieldName);
                  }
                read(mixin(fieldName));
              }
          }
      }
  }
  static foreach(i; 0 .. T.length)
    {
      static if (isBasicType!(T[i]) || is(T[i] == string))
        basicTypeRead(t[i]);
      else static if (is(typeof({foreach(ref e; t[i]){}})))
        iterableRead(t[i]);
      else static if (isTuple!(T[i]))
        tupleRead(t[i]);
      else static if (isAggregateType!(T[i]))
        structRead(t[i]);
    }
}

auto next(T)()
{
  T t;
  read(t);
  return t;
}

size_t ind(T)(T t)
{
  return cast(size_t)t;
}

ref auto at(R, I)(ref R r, I i)
{
  return r[cast(size_t)i];
}

void set(R, I, V)(ref R r, I i, V v)
{
  r[cast(size_t)i] = v;
}

import std.conv;
import std.traits;
import std.meta;
int _loglevel = -1;
void _log(string functionName, argSeq...)()
{
  foreach(i; 0 .. _loglevel * 4)
    write(' ');
  write(functionName);
  static foreach(arg; argSeq)
    {
      write(" ", arg.stringof, " = ", arg);
    }
  writeln;
}
enum logCall =
  q{
    debug
    {
     {
     _loglevel++;
     alias _parameterTuple = ParameterIdentifierTuple!(mixin(split(__FUNCTION__, ".").back));
     static if (_parameterTuple.length > 0)
       mixin(`_log!(__FUNCTION__, `, [_parameterTuple].joiner(", ").array, `);`);
     else
       _log!(__FUNCTION__);
      }
     foreach(i; 0 .. _loglevel * 4) write(' ');
     writeln('{');
     scope(exit)
       {
         foreach(i; 0 .. _loglevel * 4) write(' ');
         writeln('}');
         _loglevel--;
       }
    }
};

void logSym(S...)(int line = __LINE__, string file = __FUNCTION__)
{
  debug
    {
      foreach(i; 0 .. _loglevel * 4) write(' ');
      write(file, "(", line, "):");
      static foreach(s; S)
        write(" ", s.stringof, " = ", s);
      writeln;

    }
}

Array!E makeArray(E, S)(S size, lazy E value)
{
  auto a = Array!E();
  a.length = cast(size_t) size;
  foreach(ref ai; a)
    ai = value();
  return a;
}
Array!E makeArray(E, S)(S size)
{
  auto a = Array!E();
  a.length = cast(size_t) size;
  return a;
}

template mem(alias F)
{
  ReturnType!F[Tuple!(Parameters!F)] table;
  ReturnType!F mem(Parameters!F args)
  {
    return table.require(tuple(args), F(args));
  }
}

string input(string names, string type = "long")
{
  return text(type, " ", names, "; read(", names, ");");
}

auto pmod(T, W)(T t, W w)
{
  return (t%w + w) % w;
}

void rep(S, F)(F f, S times)
{
  static if (is(typeof(f(i))))
    foreach(i; 0 .. times)
      f(i);
  else
    foreach(i; 0 .. times)
      f();
}

void multi()
{
  foreach(tc; 0 .. next!long)
    next!TestCase.solve(tc);
}

void single()
{
  auto tc = next!TestCase;
  tc.solve;
}

void main()
{
  type;
}

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

string FMT_F = "%.10f";

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

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

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

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

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

		int[] list;
		char last = s[0];
		int cnt;
		foreach (i; 0..n)
		{
			if (s[i] != last)
			{
				list ~= cnt;
				cnt = 0;
			}
			++cnt;
			last = s[i];
		}
		if (!list.empty && s[0] == s[$-1])
		{
			list[0] += cnt;
		}
		else
		{
			list ~= cnt;
		}

		if (list.length == 1)
		{
			ans[ti] += (list[0] + 2) / 3;
		}
		else
		{
			foreach (e; list)
				ans[ti] += e / 3;
		}
	}

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


You are a coach of a group consisting of $$$n$$$ students. The $$$i$$$-th student has programming skill $$$a_i$$$. All students have distinct programming skills. You want to divide them into teams in such a way that:  No two students $$$i$$$ and $$$j$$$ such that $$$|a_i - a_j| = 1$$$ belong to the same team (i.e. skills of each pair of students in the same team have the difference strictly greater than $$$1$$$);  the number of teams is the minimum possible. You have to answer $$$q$$$ independent queries.

The first line of the input contains one integer $$$q$$$ ($$$1 \le q \le 100$$$) — the number of queries. Then $$$q$$$ queries follow. The first line of the query contains one integer $$$n$$$ ($$$1 \le n \le 100$$$) — the number of students in the query. The second line of the query contains $$$n$$$ integers $$$a_1, a_2, \dots, a_n$$$ ($$$1 \le a_i \le 100$$$, all $$$a_i$$$ are distinct), where $$$a_i$$$ is the programming skill of the $$$i$$$-th student.

For each query, print the answer on it — the minimum number of teams you can form if no two students $$$i$$$ and $$$j$$$ such that $$$|a_i - a_j| = 1$$$ may belong to the same team (i.e. skills of each pair of students in the same team has the difference strictly greater than $$$1$$$)

NoteIn the first query of the example, there are $$$n=4$$$ students with the skills $$$a=[2, 10, 1, 20]$$$. There is only one restriction here: the $$$1$$$-st and the $$$3$$$-th students can't be in the same team (because of $$$|a_1 - a_3|=|2-1|=1$$$). It is possible to divide them into $$$2$$$ teams: for example, students $$$1$$$, $$$2$$$ and $$$4$$$ are in the first team and the student $$$3$$$ in the second team.In the second query of the example, there are $$$n=2$$$ students with the skills $$$a=[3, 6]$$$. It is possible to compose just a single team containing both students.

module _template;
import std.stdio;
import std.string;
import std.algorithm;
import std.container;
import std.range;
import std.math;
import std.numeric;
import std.conv;
import std.typecons;
import std.format;

struct IO {
        string read_string() {
                while (tokens.empty) {
                tokens = readln.split;
        }
        auto token = tokens.front;
                tokens.popFront;
                return token;
        }

        int read_int() {
                return read_string.to!int;
        }

        double read_double() {
                return read_string.to!double;
        }

        string[] tokens;
}

void main() {
        IO cin;
        int t = 1;
        t = cin.read_int;
        while (t--) {
                int n = cin.read_int;
                int[] arr = new int[n];
                foreach (ref i; arr) {
                        i = cin.read_int;
                }
                sort(arr);
                int ans = 1;
                for (int i = 1; i < n; i++) {
                        if (abs(arr[i] - arr[i - 1]) == 1) {
                                ans = 2;
                        }
                }
                writeln(ans);
        }
}

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; }
T[] RDA(T = long)(T fix = 0) { auto r = readln.chomp.split.to!(T[]); r[] += fix; return r; }
T[][] RDA2(T = long)(size_t n, T[] fix = []) { auto r = new T[][](n); foreach (i; 0..n) { r[i] = readln.chomp.split.to!(T[]); foreach (j, e; fix) r[i][j] += e; } return r; }
size_t[] MAKE_IDX(alias less = "a < b", Range)(Range range) { auto idx = new size_t[](range.length); makeIndex!(less)(range, idx); return idx;}
size_t MIN_POS(alias less = "a < b", Range)(Range range) { auto r = minPos!(less)(range); return range.length - r.length; }

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

long mod = 10^^9 + 7;
//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 main()
{
	auto q = RD!int;
	auto ans = new long[](q);
	foreach (i; 0..q)
	{
		auto n = RD!int;
		auto a = RDA;
		a.sort();
		foreach (j; 1..n)
		{
			if (a[j]-1 == a[j-1])
			{
				ans[i] = 1;
				break;
			}
		}
	}

	foreach (e; ans)
		writeln(e+1);

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

module _template;
import std.stdio;
import std.string;
import std.algorithm;
import std.container;
import std.range;
import std.math;
import std.numeric;
import std.conv;
import std.typecons;
import std.format;

struct IO {
        string read_string() {
                while (tokens.empty) {
                tokens = readln.split;
        }
        auto token = tokens.front;
                tokens.popFront;
                return token;
        }

        int read_int() {
                return read_string.to!int;
        }

        double read_double() {
                return read_string.to!double;
        }

        string[] tokens;
}

void main() {
        IO cin;
        int t = 1;
        t = cin.read_int;
        while (t--) {
                int n = cin.read_int;
                int even = 0;
                int odd = 0;
                int[] arr = new int[n];
                for (int i = 0; i < n; i++) {
                        arr[i] = cin.read_int;
                        if (arr[i] % 2 == 0) even++;
                        else odd++;
                }
                if (even == 1 && odd == 1) writeln(1);
                else if (even && !odd) writeln(1);
                else if (odd && !even) writeln(1);
                else writeln(2);
        }
}


There are $$$n$$$ stones arranged on an axis. Initially the $$$i$$$-th stone is located at the coordinate $$$s_i$$$. There may be more than one stone in a single place.You can perform zero or more operations of the following type:   take two stones with indices $$$i$$$ and $$$j$$$ so that $$$s_i \leq s_j$$$, choose an integer $$$d$$$ ($$$0 \leq 2 \cdot d \leq s_j - s_i$$$), and replace the coordinate $$$s_i$$$ with $$$(s_i + d)$$$ and replace coordinate $$$s_j$$$ with $$$(s_j - d)$$$. In other words, draw stones closer to each other. You want to move the stones so that they are located at positions $$$t_1, t_2, \ldots, t_n$$$. The order of the stones is not important — you just want for the multiset of the stones resulting positions to be the same as the multiset of $$$t_1, t_2, \ldots, t_n$$$.Detect whether it is possible to move the stones this way, and if yes, construct a way to do so. You don't need to minimize the number of moves.

The first line contains a single integer $$$n$$$ ($$$1 \le n \le 3 \cdot 10^5$$$) – the number of stones. The second line contains integers $$$s_1, s_2, \ldots, s_n$$$ ($$$1 \le s_i \le 10^9$$$) — the initial positions of the stones. The second line contains integers $$$t_1, t_2, \ldots, t_n$$$ ($$$1 \le t_i \le 10^9$$$) — the target positions of the stones.

If it is impossible to move the stones this way, print "NO". Otherwise, on the first line print "YES", on the second line print the number of operations $$$m$$$ ($$$0 \le m \le 5 \cdot n$$$) required. You don't have to minimize the number of operations. Then print $$$m$$$ lines, each containing integers $$$i, j, d$$$ ($$$1 \le i, j \le n$$$, $$$s_i \le s_j$$$, $$$0 \leq 2 \cdot d \leq s_j - s_i$$$), defining the operations. One can show that if an answer exists, there is an answer requiring no more than $$$5 \cdot n$$$ operations.

NoteConsider the first example.   After the first move the locations of stones is $$$[2, 2, 6, 5, 9]$$$.  After the second move the locations of stones is $$$[2, 3, 5, 5, 9]$$$.  After the third move the locations of stones is $$$[2, 5, 5, 5, 7]$$$.  After the last move the locations of stones is $$$[4, 5, 5, 5, 5]$$$.

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

alias Record = Tuple !(int, q{value}, int, q{num});

void main ()
{
	int n;
multitest_loop:
	while (readf (" %s", &n) > 0)
	{
		readln;
		auto a = readln.splitter.map !(to !(int)).array;
		auto b = readln.splitter.map !(to !(int)).array;
		Record [] p;
		p.reserve (n);
		foreach (i, x; a)
		{
			p ~= Record (x, i.to !(int) + 1);
		}
		sort (p);
		sort (b);

		int [] [] ans;
		int j = 0;
		foreach (i; 0..n)
		{
			int left = b[i] - p[i].value;
			while (left > 0)
			{
				while (j < i)
				{
					j += 1;
				}
				while (j < n && p[j].value <= b[j])
				{
					j += 1;
				}
				if (j >= n)
				{
					break;
				}
				int add = min (left, p[j].value - b[j]);
				left -= add;
				p[i].value += add;
				p[j].value -= add;
				ans ~= [p[i].num, p[j].num, add];
			}
		}

		foreach (i; 0..n)
		{
			if (p[i].value != b[i])
			{
				writeln ("NO");
				continue multitest_loop;
			}
		}

		writeln ("YES");
		writeln (ans.length);
		writefln ("%(%(%s %)\n%)", ans);
	}
}

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

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

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

	int n = read.to!int;

	X[] ss;
	foreach(i; 0 .. n) ss ~= new X(i, read.to!long, 0);
	ss.sort!"a.v<b.v"();
	print!1("ss:", ss);

	long[] ts;
	foreach(i; 0 .. n) ts ~= read.to!long;
	ts.sort!"a<b"();
	print!1("ts:", ts);

	foreach(i, s; ss) s.d = ts[i] - s.v;
	print!1("ss:", ss);

	long tmp;
	foreach(s; ss){
		tmp += s.d;
		if(tmp < 0){
			"NO".writeln;
			return;
		}
	}
	if(tmp > 0){
		"NO".writeln;
		return;
	}

	X[] ps, qs;
	foreach(s; ss){
		if(s.d > 0) ps ~= s;
		if(s.d < 0) qs ~= s;
	}
	print!1("ps:", ps);
	print!1("qs:", qs);

	A[] ans;
	int j;
	foreach(p; ps){
		print!1("p:", p);
		while(p.d > 0){
			X q = qs[j];
			if(!(q.d < 0)){
				j += 1;
				continue;
			}
			if(p.d + q.d > 0){
				ans ~= A(p.id + 1, q.id + 1, -q.d);
				p.d += q.d;
				q.d = 0;
			}
			else{
				ans ~= A(p.id + 1, q.id + 1, p.d);
				q.d += p.d;
				p.d = 0;
			}
		}
		print!1("ans:", ans);
	}

	"YES".writeln;
	ans.length.writeln;
	foreach(an; ans){
		writeln(an.i, " ", an.j, " ", an.d);
	}

}

class X{
	int id;
	long v;
	long d;
	this(int id, long v, long d){
		this.id = id;
		this.v = v;
		this.d = d;
	}
	override string toString(){
		return id.to!string ~ " " ~ v.to!string ~ " " ~ d.to!string;
	}
}

struct A{
	int i, j;
	long d;
}