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

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


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

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


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


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


import core.bitop, std.bitmanip;
import core.checkedint;
import std.algorithm, std.functional, std.meta;
import std.array, std.container;
import std.bigint;
import std.conv;
import std.math, std.numeric;
import std.range, std.range.interfaces;
import std.stdio, std.string;
import std.ascii, std.typecons;

struct r {
    int h, w, idx;
};

void main()
{
    auto t = readln.chomp.to!int;

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

        auto a = new r[] (n);
        foreach (i; 0 .. n) {
            readf("%s %s", &a[i].h, &a[i].w);
            readln;

            a[i].idx = i;
        }

        foreach (i; 0 .. n) {
            if (a[i].h > a[i].w) { swap(a[i].h, a[i].w); }
        }

        a.schwartzSort!(x => x.h);
        int mn = -1, nxtmn = 0;

        auto ans = new int[] (n);
        ans[a[0].idx] = -1;

        foreach (i; 1 .. n) {
            if (a[i].h > a[i-1].h) { mn = nxtmn; }

            ans[a[i].idx] = mn != -1 && a[mn].w < a[i].w ? a[mn].idx : -1;

            if (a[i].w < a[nxtmn].w) { nxtmn = i; }
        }

        ans.map!(x => x != -1 ? x+1 : -1).map!(to!string).join(" ").writeln;
    }
}

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

void main ()
{
	auto tests = readln.strip.to !(int);
	foreach (test; 0..tests)
	{
		int n;
		readf !(" %s") (n);
		alias Friend = Tuple !(int, q{w}, int, q{h}, int, q{id});
		auto f = new Friend [n * 2];
		foreach (i; 0..n)
		{
			int w, h;
			readf !(" %s %s") (w, h);
			f[i * 2 + 0] = Friend (w, h, i);
			f[i * 2 + 1] = Friend (h, w, i);
		}
		sort (f);
		auto lo = f.front;
		auto answer = (-1).repeat (n).array;
		int j = 0;
		foreach (ref c; f)
		{
			while (f[j].w < c.w)
			{
				if (lo.h > f[j].h)
				{
					lo = f[j];
				}
				j += 1;
			}
			if (lo.w < c.w && lo.h < c.h)
			{
				answer[c.id] = lo.id + 1;
			}
		}
		writefln !("%(%s %)") (answer);
	}
}

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(ref long x, long y) { x = (x + y) % mod; }
void mods(ref long x, long y) { x = ((x + mod) - (y % mod)) % mod; }
void modm(ref long x, long y) { x = (x * y) % mod; }
void modpow(ref long x, long y) { if (!y) { x = 1; return; } auto t = x; x.modpow(y>>1); x.modm(x); if (y&1) x.modm(t); }
void modd(ref long x, long y) { y.modpow(mod - 2); x.modm(y); }

void main()
{
	auto t = RD!int;
	auto ans = new int[][](t);
	foreach (ti; 0..t)
	{
		auto n = RD!int;
		auto h = new long[](n);
		auto w = new long[](n);
		foreach (i; 0..n)
		{
			h[i] = RD;
			w[i] = RD;
		}

		auto tmp = new int[](n);
		tmp[] = -1;

		auto list = new long[][](n*2);
		foreach (i; 0..n)
		{
			list[i*2] = [h[i], w[i], i];
			list[i*2+1] = [w[i], h[i], i];
		}
		auto index = list.MAKE_IDX!"a[0] == b[0] ? a[1] > b[1] : a[0] < b[0]";
		long minW = long.max;
		int posW;
		foreach (i; index)
		{
			auto hh = list[i][0];
			auto ww = list[i][1];
			auto jj = cast(int)list[i][2];
			if (minW < ww)
			{
				tmp[jj] = posW+1;
			}
			if (ww < minW)
			{
				minW = ww;
				posW = jj;
			}
		}

		ans[ti] = tmp;
	}

	foreach (e; ans)
		e.map!(to!string).join(" ").writeln;
	stdout.flush;
	debug readln;
}

import core.bitop, std.bitmanip;
import core.checkedint;
import std.algorithm, std.functional, std.meta;
import std.array, std.container;
import std.bigint;
import std.conv;
import std.math, std.numeric;
import std.range, std.range.interfaces;
import std.stdio, std.string;
import std.ascii, std.typecons;

struct r {
    int h, w, idx;
};

void main()
{
    auto t = readln.chomp.to!int;

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

        auto a = new r[] (n);
        foreach (i; 0 .. n) {
            readf("%s %s", &a[i].h, &a[i].w);
            readln;
            a[i].idx = i;
        }

        a.schwartzSort!(x => x.h);
        int mn = -1, nxtmn = 0;

        auto ans = new int[] (n);
        ans[a[0].idx] = -1;

        foreach (i; 1 .. n) {
            if (a[i].h > a[i-1].h) { mn = nxtmn; }

            ans[a[i].idx] = mn != -1 && a[mn].w < a[i].w ? a[mn].idx : -1;

            if (a[i].w < a[nxtmn].w) { nxtmn = i; }
        }

        ans.map!(x => x != -1 ? x+1 : -1).map!(to!string).join(" ").writeln;
    }
}

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

string FMT_F = "%.10f";

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

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

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

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

void main()
{
	auto t = RD!int;
	auto ans = new int[][](t);
	foreach (ti; 0..t)
	{
		auto n = RD!int;
		auto h = new long[](n);
		auto w = new long[](n);
		foreach (i; 0..n)
		{
			h[i] = RD;
			w[i] = RD;
		}

		auto tmp = new int[](n);
		tmp[] = -1;

		auto list = new long[][](n*2);
		foreach (i; 0..n)
		{
			list[i*2] = [h[i], w[i], i];
			list[i*2+1] = [w[i], h[i], i];
		}
		auto index = list.MAKE_IDX!"a[0] < b[0]";
		long minW = long.max;
		int posW;
		foreach (i; index)
		{
			auto hh = list[i][0];
			auto ww = list[i][1];
			auto jj = cast(int)list[i][2];
			if (minW < ww)
			{
				tmp[jj] = posW+1;
			}
			if (ww < minW)
			{
				minW = ww;
				posW = jj;
			}
		}

		ans[ti] = tmp;
	}

	foreach (e; ans)
		e.map!(to!string).join(" ").writeln;
	stdout.flush;
	debug readln;
}

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

void main ()
{
	auto tests = readln.strip.to !(int);
	foreach (test; 0..tests)
	{
		int n;
		readf !(" %s") (n);
		alias Friend = Tuple !(int, q{w}, int, q{h}, int, q{id});
		auto f = new Friend [n * 2];
		foreach (i; 0..n)
		{
			int w, h;
			readf !(" %s %s") (w, h);
			f[i * 2 + 0] = Friend (w, h, i);
			f[i * 2 + 1] = Friend (h, w, i);
		}
		sort (f);
		auto lo = f.front;
		auto answer = (-1).repeat (n).array;
		foreach (ref c; f)
		{
			if (lo.h > c.h)
			{
				lo = c;
			}
			if (lo.w < c.w && lo.h < c.h)
			{
				answer[c.id] = lo.id + 1;
			}
		}
		writefln !("%(%s %)") (answer);
	}
}