import std.stdio;
import std.uni;
import std.conv;
import std.container;
import std.functional;
import std.algorithm;
import std.array;
import std.typecons;
import std.range;
import std.numeric;
import core.memory;
enum mod = 1_000_000_000 + 7;

alias M = Mod!(long, mod);
alias Mx = Mat!(M, 2);

void main(string[] args)
{
  auto n = next!int;
  auto k = next!long;
  auto a = next!long(n);
  auto values = (Mx.define((i, j) => M((a[i] ^ a[j]).bitCnt % 3 == 0),n, n)^^(k - 1))[];
  values.sum.writeln;
}
ulong bitCnt(long x)
{
  pragma(inline, true);
  ulong cnt = 0;
  while(x) {cnt += x & 1; x>>=1;}
  return cnt;
}
struct Mat(T, size_t dimension)
{
  T[] _slice;
  size_t[dimension] _sizes; size_t dim(size_t i) {return _sizes[i];}
  size_t[dimension] _indexer;
  static if (dimension == 2)
    static Mat!(T, dimension) define(S...)(T delegate(size_t, size_t) F, S sizes)
    {
      pragma(inline, true);
      auto res = Mat!(T, dimension)(sizes);
      with(res)
      foreach(i; 0 .. sizes[0])
	foreach(j; 0 .. sizes[1])
	  res[i, j] = F(i, j);
      return res;
    }
  this(S...)(S sizes)
  {
    static assert(sizes.length == dimension);
    _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];
    _slice = new T[](requiredSize);
  }
  ref auto opIndex()
  {
    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
      {
	static assert(0);
	version(none)
	  {
	    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()
      {
	pragma(inline, true);
	debug assert(dim(0) == dim(1));
	auto n = dim(0);
	return Mat!(T, 2).define((i, j) => T(i == j), n, n);
      }
      bool canMultiply(Mat!(T, 2) b)
      {
	return this.dim(1) == b.dim(0);
      }
      version(none) auto opBinary(string op)(Mat!(T, 2) b)
	if (op == "*")
	  {
	    pragma(inline, true);
	    debug assert(canMultiply(b));
	    auto res = Mat!(T, 2)([this.dim(0), b.dim(1)]);
	    T mul;
	    foreach(i; 0 .. res.dim(0))
	      foreach(k; 0 .. this.dim(1)) if ((mul = this[i, k]) != T(0))
		foreach(j; 0 .. res.dim(1))
		  res[i, j] += this[i, k] * b[k, j];
	    return res;
	  }

      auto opOpAssign(string op)(Mat!(T, 2) b)
	if (op == "*")
	  {
	    pragma(inline, true);
	    debug assert(canMultiply(b));
	    auto res = Mat!(T, 2)(this.dim(0), b.dim(1));
	    res[][] = T(0);
	    foreach(i; 0 .. res.dim(0))
	      foreach(k; 0 .. this.dim(1))
		foreach(j; 0 .. res.dim(1))
		  res[i, j] += this[i, k] * b[k, j];
	    this[][] = res[][];
	    return this;
	  }

      auto opBinary(string op)(ulong exp)
	if (op == "^^")
	  {
	    pragma(inline, true);
	    return this.pow(identity, exp);
	  }
      mixin interiorBinPow;
    }
}

struct Mod(T, long mod)
{
  alias This = Mod!(T, mod);
  T rep;
  string toString()
  {
    return to!string(rep);
  }
  static auto makeSafe(T t)
  {
    if (t >= 0) return Mod!(T, mod)(t % mod);
    return Mod!(T, mod)(t % mod + mod);
  }
  auto opBinary(string op)(This b)
  {
    pragma(inline, true);
    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((rep * b.rep)%mod);
      }
  }
  auto opOpAssign(string op)(This b)
  {
    pragma(inline, true);
    static if (op == "+")
      {
	this.rep += b.rep;
	if (this.rep >= mod) this.rep -= mod;
      }
    else static if (op == "-")
      {
	this.rep -= b.rep;
	if (this.rep < 0) this.rep += mod;
      }
    else static if (op == "*")
      {
	this.rep *= b.rep;
	this.rep %= mod;
      }
  }
}

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

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

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

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

import std.stdio;
import std.uni;
import std.conv;
import std.container;
import std.functional;
import std.algorithm;
import std.array;
import std.typecons;
import std.range;
import std.numeric;
import core.memory;
enum mod = 1_000_000_000 + 7;

alias M = Mod!(long, mod);
alias Mx = Mat!(M, 2);

void main(string[] args)
{
  auto n = next!int;
  auto k = next!long;
  auto a = next!long(n);
  auto values = (Mx.define((i, j) => M((a[i] ^ a[j]).bitCnt % 3 == 0),n, n)^^(k - 1))[];
  values.sum.writeln;
}
ulong bitCnt(long x)
{
  pragma(inline, true);
  ulong cnt = 0;
  while(x) {cnt += x & 1; x>>=1;}
  return cnt;
}
struct Mat(T, size_t dimension)
{
  T[] _slice;
  size_t[dimension] _sizes; size_t dim(size_t i) {return _sizes[i];}
  size_t[dimension] _indexer;
  static if (dimension == 2)
    static Mat!(T, dimension) define(S...)(T delegate(size_t, size_t) F, S sizes)
    {
      pragma(inline, true);
      auto res = Mat!(T, dimension)(sizes);
      with(res)
      foreach(i; 0 .. sizes[0])
	foreach(j; 0 .. sizes[1])
	  res[i, j] = F(i, j);
      return res;
    }
  this(S...)(S sizes)
  {
    static assert(sizes.length == dimension);
    _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];
    _slice = new T[](requiredSize);
  }
  ref auto opIndex()
  {
    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
      {
	static assert(0);
	version(none)
	  {
	    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()
      {
	pragma(inline, true);
	debug assert(dim(0) == dim(1));
	auto n = dim(0);
	return Mat!(T, 2).define((i, j) => T(i == j), n, n);
      }
      bool canMultiply(Mat!(T, 2) b)
      {
	return this.dim(1) == b.dim(0);
      }
      version(none) auto opBinary(string op)(Mat!(T, 2) b)
	if (op == "*")
	  {
	    pragma(inline, true);
	    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] += this[i, k] * b[k, j];
	    return res;
	  }

      auto opOpAssign(string op)(Mat!(T, 2) b)
	if (op == "*")
	  {
	    pragma(inline, true);
	    debug assert(canMultiply(b));
	    auto res = Mat!(T, 2)(this.dim(0), b.dim(1));
	    res[][] = T(0);
	    foreach(i; 0 .. res.dim(0))
	      foreach(k; 0 .. this.dim(1))
		foreach(j; 0 .. res.dim(1))
		  res[i, j] += this[i, k] * b[k, j];
	    this[][] = res[][];
	    return this;
	  }

      auto opBinary(string op)(ulong exp)
	if (op == "^^")
	  {
	    pragma(inline, true);
	    return this.pow(identity, exp);
	  }
      mixin interiorBinPow;
    }
}

struct Mod(T, long mod)
{
  alias This = Mod!(T, mod);
  T rep;
  string toString()
  {
    return to!string(rep);
  }
  static auto makeSafe(T t)
  {
    if (t >= 0) return Mod!(T, mod)(t % mod);
    return Mod!(T, mod)(t % mod + mod);
  }
  auto opBinary(string op)(This b)
  {
    pragma(inline, true);
    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((rep * b.rep)%mod);
      }
  }
  auto opOpAssign(string op)(This b)
  {
    pragma(inline, true);
    static if (op == "+")
      {
	this.rep += b.rep;
	if (this.rep >= mod) this.rep -= mod;
      }
    else static if (op == "-")
      {
	this.rep -= b.rep;
	if (this.rep < 0) this.rep += mod;
      }
    else static if (op == "*")
      {
	this.rep *= b.rep;
	this.rep %= mod;
      }
  }
}

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

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

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

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

import std.stdio;
import std.uni;
import std.conv;
import std.container;
import std.functional;
import std.algorithm;
import std.array;
import std.typecons;
import std.range;
import std.numeric;
import core.memory;
enum mod = 1_000_000_000 + 7;

alias M = Mod!(long, mod);
alias Mx = StaticMat!(M, 100, 100);

void main(string[] args)
{
  auto n = next!int;
  auto k = next!long;
  auto a = next!long(n);
  auto values = Mx.def(n, n, (i, j) => M((a[i] ^ a[j]).bitCnt % 3 == 0))^^(k - 1);
  auto sum = M(0);
  foreach(i; 0 .. n)
    foreach(j; 0 .. n)
      sum += values[i][j];
  return sum.writeln;
}
ulong bitCnt(long x)
{
  pragma(inline, true);
  ulong cnt = 0;
  while(x) {cnt += x & 1; x>>=1;}
  return cnt;
}
struct StaticMat(T, maxSizes...)
{
  enum dimension = maxSizes.length;
  size_t[dimension] size;
  this(S...)(S s)
    {
      static assert(s.length == dimension);
      size[] = [s];
    }
  StaticArray!(T, maxSizes) at;
  alias at this;
  static if (dimension == 2)
    {
      static auto def(size_t s0, size_t s1, T delegate(size_t, size_t) elem)
      {
	auto mat = StaticMat!(T, maxSizes)(s0, s1);
	foreach(i; 0 .. s0)
	  foreach(j; 0 .. s1)
	    mat[i][j] = elem(i, j);
	return mat;
      }
      auto identity()
      {
	return StaticMat!(T, maxSizes).def(size[0], size[1], (i, j) => T(cast(int)i == j));
      }
      auto opOpAssign(string op)(StaticMat!(T, maxSizes) b)
	if (op == "*")
      {
	debug assert(this.size[1] == b.size[0]);
	auto n = this.size[0];
	auto m = this.size[1];
	auto r = b.size[1];
	auto res = StaticMat!(T, maxSizes)(n, r);
	foreach(i; 0 .. n) foreach(j; 0 .. r) res[i][j] = T(0);
	T mul;
	foreach(i; 0 .. n)
	  foreach(k; 0 .. m)
	    if ((mul = this[i][k]) != T(0))
	      foreach(j; 0 .. r)
		res[i][j] += mul * b[k][j];
	version(none)
	  {
	    this.size = res.size;
	    foreach(i; 0 .. n) foreach(j; 0 .. r) this[i][j] = res[i][j];
	  }
	this = res;
      }
      auto opBinary(string op)(ulong exp)
	if (op == "^^")
	  {
	    pragma(inline, true);
	    return this.pow(identity, exp);
	  }
      mixin interiorBinPow;
    }
}

template StaticArray(T, sizes...)
{
  static if (sizes.length == 1)
    alias StaticArray = T[sizes[0]];
  else
    alias StaticArray = StaticArray!(T, sizes[1 .. $])[sizes[0]];
}

struct Mod(T, long mod)
{
  alias This = Mod!(T, mod);
  T rep;
  string toString()
  {
    return to!string(rep);
  }
  static auto makeSafe(T t)
  {
    if (t >= 0) return Mod!(T, mod)(t % mod);
    return Mod!(T, mod)(t % mod + mod);
  }
  auto opBinary(string op)(This b)
  {
    pragma(inline, true);
    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((rep * b.rep)%mod);
      }
  }
  auto opOpAssign(string op)(This b)
  {
    pragma(inline, true);
    static if (op == "+")
      {
	this.rep += b.rep;
	if (this.rep >= mod) this.rep -= mod;
      }
    else static if (op == "-")
      {
	this.rep -= b.rep;
	if (this.rep < 0) this.rep += mod;
      }
    else static if (op == "*")
      {
	this.rep *= b.rep;
	this.rep %= mod;
      }
  }
}

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

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

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

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

import std.stdio;
import std.uni;
import std.conv;
import std.container;
import std.functional;
import std.algorithm;
import std.array;
import std.typecons;
import std.range;
import std.numeric;
import core.memory;
enum mod = 1_000_000_000 + 7;

alias M = Mod!(long, mod);
alias Mx = StaticMat!(M, 100, 100);

void main(string[] args)
{
  auto n = next!int;
  auto k = next!long;
  auto a = next!long(n);
  auto values = Mx.def(n, n, (i, j) => M((a[i] ^ a[j]).bitCnt % 3 == 0))^^(k - 1);
  auto sum = M(0);
  foreach(i; 0 .. n)
    foreach(j; 0 .. n)
      sum += values[i][j];
  return sum.writeln;
}
ulong bitCnt(long x)
{
  pragma(inline, true);
  ulong cnt = 0;
  while(x) {cnt += x & 1; x>>=1;}
  return cnt;
}
struct StaticMat(T, maxSizes...)
{
  enum dimension = maxSizes.length;
  size_t[dimension] size;
  this(S...)(S s)
    {
      static assert(s.length == dimension);
      size[] = [s];
    }
  StaticArray!(T, maxSizes) at;
  alias at this;
  static if (dimension == 2)
    {
      static auto def(size_t s0, size_t s1, T delegate(size_t, size_t) elem)
      {
	auto mat = StaticMat!(T, maxSizes)(s0, s1);
	foreach(i; 0 .. s0)
	  foreach(j; 0 .. s1)
	    mat[i][j] = elem(i, j);
	return mat;
      }
      auto identity()
      {
	return StaticMat!(T, maxSizes).def(size[0], size[1], (i, j) => T(cast(int)i == j));
      }
      auto opOpAssign(string op)(StaticMat!(T, maxSizes) b)
	if (op == "*")
      {
	debug assert(this.size[1] == b.size[0]);
	auto n = this.size[0];
	auto m = this.size[1];
	auto r = b.size[1];
	auto res = StaticMat!(T, maxSizes)(n, r);
	foreach(i; 0 .. n) foreach(j; 0 .. r) res[i][j] = T(0);
	T mul;
	foreach(i; 0 .. n)
	  foreach(k; 0 .. m)
	    if ((mul = this[i][k]) != T(0))
	      foreach(j; 0 .. r)
		res[i][j] += mul * b[k][j];
	version(none)
	  {
	    this.size = res.size;
	    foreach(i; 0 .. n) foreach(j; 0 .. r) this[i][j] = res[i][j];
	  }
	this = res;
      }
      auto opBinary(string op)(ulong exp)
	if (op == "^^")
	  {
	    pragma(inline, true);
	    return this.pow(identity, exp);
	  }
      mixin interiorBinPow;
    }
}

template StaticArray(T, sizes...)
{
  static if (sizes.length == 1)
    alias StaticArray = T[sizes[0]];
  else
    alias StaticArray = StaticArray!(T, sizes[1 .. $])[sizes[0]];
}

struct Mod(T, long mod)
{
  alias This = Mod!(T, mod);
  T rep;
  string toString()
  {
    return to!string(rep);
  }
  static auto makeSafe(T t)
  {
    if (t >= 0) return Mod!(T, mod)(t % mod);
    return Mod!(T, mod)(t % mod + mod);
  }
  auto opBinary(string op)(This b)
  {
    pragma(inline, true);
    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((rep * b.rep)%mod);
      }
  }
  auto opOpAssign(string op)(This b)
  {
    pragma(inline, true);
    static if (op == "+")
      {
	this.rep += b.rep;
	if (this.rep >= mod) this.rep -= mod;
      }
    else static if (op == "-")
      {
	this.rep -= b.rep;
	if (this.rep < 0) this.rep += mod;
      }
    else static if (op == "*")
      {
	this.rep *= b.rep;
	this.rep %= mod;
      }
  }
}

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

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

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

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

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

enum mod = 1_000_000_000 + 7;
int n;
long k;
long[] a;
alias M = Mod!(long, mod);
alias Mx = Matrix!(M, n, n);

void main(string[] args)
{
  n = next!int;
  k = next!long;
  a = next!long(n);
  auto mx = Mx(0);
  foreach(i; 0 .. n)
    foreach(j; 0 .. n)
      mx[i][j] = M((a[i] ^ a[j]).bitCnt % 3 == 0);
  auto pow = mx.pow(k - 1);
  auto res = M(0);
  foreach(i; 0 .. n)
    foreach(j; 0 .. n)
      res += pow[i][j];
  res.writeln;
}

ulong bitCnt(long x)
{
  pragma(inline, true);
  ulong cnt = 0;
  while(x) {cnt += x & 1; x>>=1;}
  return cnt;
}

static this()
{
  popChar;
}

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

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

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

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

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

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

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

enum mod = 1_000_000_000 + 7;
void mul(T, size_t s)(out T[s][s] res, ref T[s][s] a, ref T[s][s] b)
{
  foreach(i; 0 .. s) foreach(j; 0 .. s) res[i][j] = T(0);
  foreach(i; 0 .. s)
    foreach(k; 0 .. s)
      foreach(j; 0 .. s)
	res[i][j] = (res[i][j] + (a[i][k] * b[k][j])%mod)%mod;
}

void main(string[] args)
{
  alias M = long;
  auto n = next!int;
  auto k = next!long;
  auto a = next!long(n);
  debug writeln(n, k, a);
  M[100][100] pow, tmp, res;
  foreach(i, ai; a)
    foreach(j, aj; a)
      pow[i][j] = M((ai ^ aj).bitCnt % 3 == 0);
  foreach(i; 0 .. n) res[i][i] = M(1);
  k--;
  while(k)
    {
      if (k & 1)
	{
	  mul(tmp, res, pow);
	  res = tmp;
	}
      mul(tmp, pow, pow);
      pow = tmp;
      k >>= 1;
    }
  auto sum = M(0);
  foreach(i; 0 .. n)
    foreach(j; 0 .. n)
      sum = (sum + res[i][j]) % mod;
  sum.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[] _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)
  {
    _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];
  }
  version(none) 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()
  {
    return _slice[];
  }
  ref auto opIndex(I...)(I i)
  {
    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)
    {
      static bool identitySet = false;
      static Mat!(T, 2) _identity;
      static T[100 * 100] _identityBuff;
      auto identity()
      {
	if (identitySet) return _identity;
	debug assert(dim(0) == dim(1));
	auto n = dim(0);
	_identity = Mat!(T, 2)(_identityBuff, [n, n]);
	foreach(k; 0 .. n)
	  _identity[k, k] = T(1);
	identitySet = true;
	return _identity;
      }
      bool canMultiply(Mat!(T, 2) b)
      {
	return this.dim(1) == b.dim(0);
      }
      version(none) 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 opOpAssign(string op)(Mat!(T, 2) b)
	if (op == "*")
	  {
	    static T[100 * 100] resBuff;
	    debug assert(canMultiply(b));
	    auto res = Mat!(T, 2)(resBuff, [this.dim(0), b.dim(1)]);
	    res[][] = T(0);
	    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];
	    this[][] = res[][];
	    return this;
	  }

      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)
  {
    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)
  {
    pragma(inline, true);
    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);
      }
  }
}

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

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

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

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

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

enum mod = 1_000_000_000 + 7;
int n;
long k;
long[] a;
alias M = Mod!(long, mod);
alias Mx = Matrix!(M, n, n);

void main(string[] args)
{
  n = next!int;
  k = next!long;
  a = next!long(n);
  auto mx = Mx(0);
  foreach(i; 0 .. n)
    foreach(j; 0 .. n)
      mx[i][j] = M((a[i] ^ a[j]).bitCnt % 3 == 0);
  auto pow = mx.pow(k - 1);
  auto res = M(0);
  foreach(i; 0 .. n)
    foreach(j; 0 .. n)
      res += pow[i][j];
  res.writeln;
}

ulong bitCnt(long x)
{
  pragma(inline, true);
  ulong cnt = 0;
  while(x) {cnt += x & 1; x>>=1;}
  return cnt;
}

static this()
{
  popChar;
}

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

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

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

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

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

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

import std.stdio;
import std.uni;
import std.conv;
import std.container;
import std.functional;
import std.algorithm;
import std.array;
import std.typecons;
import std.range;
import std.numeric;
import core.memory;
enum mod = 1_000_000_000 + 7;

alias M = Mod!(long, mod);
alias Mx = StaticMat!(M, 100, 100);

void main(string[] args)
{
  auto n = next!int;
  auto k = next!long;
  auto a = next!long(n);
  (Mx.def(n, n, (i, j) => M((a[i] ^ a[j]).bitCnt % 3 == 0))^^(k - 1))[].sum.writeln;
}
ulong bitCnt(long x)
{
  pragma(inline, true);
  ulong cnt = 0;
  while(x) {cnt += x & 1; x>>=1;}
  return cnt;
}
struct StaticMat(T, maxSizes...)
{
  enum dimension = maxSizes.length;
  size_t[dimension] size;
  this(S...)(S s)
    {
      static assert(s.length == dimension);
      size[] = [s];
      this[][] = T(0);
    }
  StaticArray!(T, maxSizes) at;
  auto opSlice()
  {
    return (cast(T*)at.ptr)[0 .. arrSize!(maxSizes)][];
  }
  alias at this;
  static if (dimension == 2)
    {
      static auto def(size_t s0, size_t s1, T delegate(size_t, size_t) elem)
      {
	auto mat = StaticMat!(T, maxSizes)(s0, s1);
	foreach(i; 0 .. s0)
	  foreach(j; 0 .. s1)
	    mat[i][j] = elem(i, j);
	return mat;
      }
      auto identity()
      {
	return StaticMat!(T, maxSizes).def(size[0], size[1], (i, j) => T(cast(int)i == j));
      }
      auto opOpAssign(string op)(StaticMat!(T, maxSizes) b)
	if (op == "*")
      {
	debug assert(this.size[1] == b.size[0]);
	auto n = this.size[0];
	auto m = this.size[1];
	auto r = b.size[1];
	auto res = StaticMat!(T, maxSizes)(n, r);
	res[][] = T(0);
	T mul;
	foreach(i; 0 .. n)
	  foreach(k; 0 .. m)
	    if ((mul = this[i][k]) != T(0))
	      foreach(j; 0 .. r)
		res[i][j] += mul * b[k][j];
	this = res;
      }
      auto opBinary(string op)(ulong exp)
	if (op == "^^")
	  {
	    pragma(inline, true);
	    return this.pow(identity, exp);
	  }
      mixin interiorBinPow;
    }
}

template StaticArray(T, sizes...)
{
  static if (sizes.length == 1)
    alias StaticArray = T[sizes[0]];
  else
    alias StaticArray = StaticArray!(T, sizes[1 .. $])[sizes[0]];
}

template arrSize(S...)
{
  static if (S.length == 1) enum arrSize = S[0];
  else enum arrSize = S[0] * arrSize!(S[1 .. $]);
}

struct Mod(T, long mod)
{
  alias This = Mod!(T, mod);
  T rep;
  string toString()
  {
    return to!string(rep);
  }
  static auto makeSafe(T t)
  {
    if (t >= 0) return Mod!(T, mod)(t % mod);
    return Mod!(T, mod)(t % mod + mod);
  }
  auto opBinary(string op)(This b)
  {
    pragma(inline, true);
    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((rep * b.rep)%mod);
      }
  }
  auto opOpAssign(string op)(This b)
  {
    pragma(inline, true);
    static if (op == "+")
      {
	this.rep += b.rep;
	if (this.rep >= mod) this.rep -= mod;
      }
    else static if (op == "-")
      {
	this.rep -= b.rep;
	if (this.rep < 0) this.rep += mod;
      }
    else static if (op == "*")
      {
	this.rep *= b.rep;
	this.rep %= mod;
      }
  }
}

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

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

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

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

import std.stdio;
import std.uni;
import std.conv;
import std.container;
import std.functional;
import std.algorithm;
import std.array;
import std.typecons;
import std.range;
import std.numeric;
import core.memory;
enum mod = 1_000_000_000 + 7;
class FreeList(T)
{
  T allocated;
  FreeList!T next = null;
  this(FreeList!T next)
  {
    this.next = next;
  }
}
long totalUse = 0;
FreeList!T alloc(T)(ref FreeList!T freeList)
{
  if (freeList is null)
    {
      totalUse++;
      return new FreeList!T(null);
    }
  else
    {
      auto ret = freeList;
      freeList = freeList.next;
      ret.next = null;
      return ret;
    }
}
void free(T)(ref FreeList!T freeList, FreeList!T t)
{
  debug assert(t.next is null);
  t.next = freeList;
  freeList = t;
}

alias M = Mod!(long, mod);
FreeList!(M[100 * 100]) mAlloc;
alias Mx = Mat!(M, 2, mAlloc);

void main(string[] args)
{
  auto n = next!int;
  auto k = next!long;
  auto a = next!long(n);
  (Mx.define((i, j) => M((a[i] ^ a[j]).bitCnt % 3 == 0),
	   n, n)^^(k - 1))[]
    .sum
    .writeln;
  if(totalUse > 2)
    {
      a[-1] = 0;
    }
}
ulong bitCnt(long x)
{
  ulong cnt = 0;
  while(x) {cnt += x & 1; x>>=1;}
  return cnt;
}
struct Mat(T, size_t dimension, alias allocator)
{
  typeof(allocator) _allocatedNode;
  T[] _slice;
  size_t[dimension] _sizes;
  size_t dim(size_t i) {return _sizes[i];}
  size_t[dimension] _indexer;
  static if (dimension == 2)
    static Mat!(T, dimension, allocator) define(S...)(T delegate(size_t, size_t) F, S sizes)
    {
      auto res = Mat!(T, dimension, allocator)(sizes);
      with(res)
      foreach(i; 0 .. sizes[0])
	foreach(j; 0 .. sizes[1])
	  res[i, j] = F(i, j);
      return res;
    }
  this(S...)(S sizes)
  {
    static assert(sizes.length == dimension);
    _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];
    _allocatedNode = allocator.alloc;
    _slice = _allocatedNode.allocated[0 .. requiredSize];
  }
  void free()
  {
    allocator.free(_allocatedNode);
  }
  ref auto opIndex()
  {
    return _slice[];
  }
  ref auto opIndex(I...)(I i)
  {
    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
      {
	static assert(0);
	version(none)
	  {
	    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, allocator)(basePortion, remSizes);
	  }
      }
  }
  static if (dimension == 2)
    {
      auto identity()
      {
	debug assert(dim(0) == dim(1));
	auto n = dim(0);
	return Mat!(T, 2, allocator).define((i, j) => T(i == j), n, n);
      }
      bool canMultiply(alias alloc)(Mat!(T, 2, alloc) b)
      {
	return this.dim(1) == b.dim(0);
      }
      version(none) auto opBinary(string op)(Mat!(T, 2, allocator) 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] += this[i, k] * b[k, j];
	    return res;
	  }

      auto opOpAssign(string op)(Mat!(T, 2, allocator) b)
	if (op == "*")
	  {
	    static T[100 * 100] resBuff;
	    debug assert(canMultiply(b));
	    auto res = Mat!(T, 2, allocator)(this.dim(0), b.dim(1));
	    res[][] = T(0);
	    foreach(i; 0 .. res.dim(0))
	      foreach(k; 0 .. this.dim(1))
		foreach(j; 0 .. res.dim(1))
		  res[i, j] += this[i, k] * b[k, j];
	    this[][] = res[][];
	    res.free;
	    return this;
	  }

      auto opBinary(string op)(ulong exp)
	if (op == "^^")
	  {
	    return this.pow(identity, exp);
	  }
      mixin interiorBinPow;
    }
}

struct Mod(T, long mod)
{
  alias This = Mod!(T, mod);
  T rep;
  string toString()
  {
    return to!string(rep);
  }
  static auto makeSafe(T t)
  {
    if (t >= 0) return Mod!(T, mod)(t % mod);
    return Mod!(T, mod)(t % mod + mod);
  }
  auto opBinary(string op)(This b)
  {
    pragma(inline, true);
    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((rep * b.rep)%mod);
      }
  }
  auto opOpAssign(string op)(This b)
  {
    pragma(inline, true);
    static if (op == "+")
      {
	this.rep += b.rep;
	if (this.rep >= mod) this.rep -= mod;
      }
    else static if (op == "-")
      {
	this.rep -= b.rep;
	if (this.rep < 0) this.rep += mod;
      }
    else static if (op == "*")
      {
	this.rep *= b.rep;
	this.rep %= mod;
      }
  }
}

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

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

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

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

import std.stdio;
import std.uni;
import std.conv;
import std.container;
import std.functional;
import std.algorithm;
import std.array;
import std.typecons;
import std.range;
import std.numeric;
import core.memory;
enum mod = 1_000_000_000 + 7;
class FreeList(T)
{
  T allocated;
  FreeList!T next = null;
  size_t size;
  this(FreeList!T next)
  {
    this.next = next;
    this.size = 1 + (next is null? 0 : next.size);
    assert(this.size <= 3);
  }
}
FreeList!T alloc(T)(ref FreeList!T freeList)
{
  if (freeList is null)
    {
      return new FreeList!T(null);
    }
  else
    {
      auto ret = freeList;
      freeList = freeList.next;
      ret.next = null;
      return ret;
    }
}
void free(T)(ref FreeList!T freeList, FreeList!T t)
{
  debug assert(t.next is null);
  t.next = freeList;
  freeList = t;
}

alias M = Mod!(long, mod);
FreeList!(M[100 * 100]) mAlloc;
alias Mx = Mat!(M, 2, mAlloc);

void main(string[] args)
{
  auto n = next!int;
  auto k = next!long;
  auto a = next!long(n);
  (Mx.define((i, j) => M((a[i] ^ a[j]).bitCnt % 3 == 0),
	   n, n)^^(k - 1))[]
    .sum
    .writeln;
}
ulong bitCnt(long x)
{
  ulong cnt = 0;
  while(x) {cnt += x & 1; x>>=1;}
  return cnt;
}
struct Mat(T, size_t dimension, alias allocator)
{
  typeof(allocator) _allocatedNode;
  T[] _slice;
  size_t[dimension] _sizes;
  size_t dim(size_t i) {return _sizes[i];}
  size_t[dimension] _indexer;
  static if (dimension == 2)
    static Mat!(T, dimension, allocator) define(S...)(T delegate(size_t, size_t) F, S sizes)
    {
      auto res = Mat!(T, dimension, allocator)(sizes);
      with(res)
      foreach(i; 0 .. sizes[0])
	foreach(j; 0 .. sizes[1])
	  res[i, j] = F(i, j);
      return res;
    }
  this(S...)(S sizes)
  {
    static assert(sizes.length == dimension);
    _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];
    _allocatedNode = allocator.alloc;
    _slice = _allocatedNode.allocated[0 .. requiredSize];
  }
  void free()
  {
    allocator.free(_allocatedNode);
  }
  ref auto opIndex()
  {
    return _slice[];
  }
  ref auto opIndex(I...)(I i)
  {
    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
      {
	static assert(0);
	version(none)
	  {
	    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, allocator)(basePortion, remSizes);
	  }
      }
  }
  static if (dimension == 2)
    {
      auto identity()
      {
	debug assert(dim(0) == dim(1));
	auto n = dim(0);
	return Mat!(T, 2, allocator).define((i, j) => T(i == j), n, n);
      }
      bool canMultiply(alias alloc)(Mat!(T, 2, alloc) b)
      {
	return this.dim(1) == b.dim(0);
      }
      version(none) auto opBinary(string op)(Mat!(T, 2, allocator) 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] += this[i, k] * b[k, j];
	    return res;
	  }

      auto opOpAssign(string op)(Mat!(T, 2, allocator) b)
	if (op == "*")
	  {
	    static T[100 * 100] resBuff;
	    debug assert(canMultiply(b));
	    auto res = Mat!(T, 2, allocator)(this.dim(0), b.dim(1));
	    res[][] = T(0);
	    foreach(i; 0 .. res.dim(0))
	      foreach(k; 0 .. this.dim(1))
		foreach(j; 0 .. res.dim(1))
		  res[i, j] += this[i, k] * b[k, j];
	    this[][] = res[][];
	    res.free;
	    return this;
	  }

      auto opBinary(string op)(ulong exp)
	if (op == "^^")
	  {
	    return this.pow(identity, exp);
	  }
      mixin interiorBinPow;
    }
}

struct Mod(T, long mod)
{
  alias This = Mod!(T, mod);
  T rep;
  string toString()
  {
    return to!string(rep);
  }
  static auto makeSafe(T t)
  {
    if (t >= 0) return Mod!(T, mod)(t % mod);
    return Mod!(T, mod)(t % mod + mod);
  }
  auto opBinary(string op)(This b)
  {
    pragma(inline, true);
    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((rep * b.rep)%mod);
      }
  }
  auto opOpAssign(string op)(This b)
  {
    pragma(inline, true);
    static if (op == "+")
      {
	this.rep += b.rep;
	if (this.rep >= mod) this.rep -= mod;
      }
    else static if (op == "-")
      {
	this.rep -= b.rep;
	if (this.rep < 0) this.rep += mod;
      }
    else static if (op == "*")
      {
	this.rep *= b.rep;
	this.rep %= mod;
      }
  }
}

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

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

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

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

import std.stdio;
import std.uni;
import std.conv;
import std.container;
import std.functional;
import std.algorithm;
import std.array;
import std.typecons;
import std.range;
import std.numeric;
import core.memory;
enum mod = 1_000_000_000 + 7;
void main(string[] args)
{
  GC.disable;
  alias M = Mod!(long, mod);
  alias Mx = Mat!(M, 2);
  M[100 * 100] basePow;
  long[100] baseA;
  auto n = next!int;
  auto k = next!long;
  auto a = Arr!long(baseA, [n]);
  foreach(ref ai; a[]) ai = next!long;
  (Mx.make((i, j) => M((a[i] ^ a[j]).bitCnt % 3 == 0),
	   basePow,
	   [n, n])^^(k - 1))[]
    .sum
    .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[] _slice;
  size_t[dimension] _sizes;
  size_t dim(size_t i) {return _sizes[i];}
  size_t[dimension] _indexer;
  static if (dimension == 2)
    static Mat!(T, dimension) make(T delegate(size_t, size_t) F, T[] baseArray, size_t[dimension] sizes)
    {
      auto res = Mat!(T, dimension)(baseArray, sizes);
      with(res)
      foreach(i; 0 .. sizes[0])
	{
	  auto row = res[i];
	  foreach(j; 0 .. sizes[1])
	    row[j] = F(i, j);
	}
      return res;
    }
  this(T[] baseArray, size_t[dimension] sizes)
  {
    _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];
  }
  version(none) 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()
  {
    return _slice[];
  }
  ref auto opIndex(I...)(I i)
  {
    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)
    {
      static bool identitySet = false;
      static Mat!(T, 2) _identity;
      static T[100 * 100] _identityBuff;
      auto identity()
      {
	if (identitySet) return _identity;
	debug assert(dim(0) == dim(1));
	auto n = dim(0);
	_identity = Mat!(T, 2)(_identityBuff, [n, n]);
	foreach(k; 0 .. n)
	  _identity[k, k] = T(1);
	identitySet = true;
	return _identity;
      }
      bool canMultiply(Mat!(T, 2) b)
      {
	return this.dim(1) == b.dim(0);
      }
      version(none) 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] += this[i, k] * b[k, j];
	    return res;
	  }

      auto opOpAssign(string op)(Mat!(T, 2) b)
	if (op == "*")
	  {
	    static T[100 * 100] resBuff;
	    debug assert(canMultiply(b));
	    auto res = Mat!(T, 2)(resBuff, [this.dim(0), b.dim(1)]);
	    res[][] = T(0);
	    foreach(i; 0 .. res.dim(0))
	      foreach(k; 0 .. this.dim(1))
		foreach(j; 0 .. res.dim(1))
		  res[i, j] += this[i, k] * b[k, j];
	    this[][] = res[][];
	    return this;
	  }

      auto opBinary(string op)(ulong exp)
	if (op == "^^")
	  {
	    return this.pow(identity, exp);
	  }
      mixin interiorBinPow;
    }
}

struct Mod(T, long mod)
{
  alias This = Mod!(T, mod);
  T rep;
  string toString()
  {
    return to!string(rep);
  }
  static auto makeSafe(T t)
  {
    if (t >= 0) return Mod!(T, mod)(t % mod);
    return Mod!(T, mod)(t % mod + mod);
  }
  auto opBinary(string op)(This b)
  {
    pragma(inline, true);
    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((rep * b.rep)%mod);
      }
  }
  auto opOpAssign(string op)(This b)
  {
    pragma(inline, true);
    static if (op == "+")
      {
	this.rep += b.rep;
	if (this.rep >= mod) this.rep -= mod;
      }
    else static if (op == "-")
      {
	this.rep -= b.rep;
	if (this.rep < 0) this.rep += mod;
      }
    else static if (op == "*")
      {
	this.rep *= b.rep;
	this.rep %= mod;
      }
  }
}

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

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

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

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

import std.stdio;
import std.uni;
import std.conv;
import std.container;
import std.functional;
import std.algorithm;
import std.array;
import std.typecons;
import std.range;
import std.numeric;
import core.memory;
enum mod = 1_000_000_000 + 7;
class FreeList(T)
{
  T allocated;
  FreeList!T next = null;
  size_t size;
  this(FreeList!T next)
  {
    this.next = next;
    this.size = 1 + (next is null? 0 : next.size);
    assert(this.size <= 5);
  }
}
FreeList!T alloc(T)(ref FreeList!T freeList)
{
  if (freeList is null)
    {
      return new FreeList!T(null);
    }
  else
    {
      auto ret = freeList;
      freeList = freeList.next;
      ret.next = null;
      return ret;
    }
}
void free(T)(ref FreeList!T freeList, FreeList!T t)
{
  debug assert(t.next is null);
  t.next = freeList;
  freeList = t;
}

alias M = Mod!(long, mod);
FreeList!(M[100 * 100]) mAlloc;
alias Mx = Mat!(M, 2, mAlloc);

void main(string[] args)
{
  auto n = next!int;
  auto k = next!long;
  auto a = next!long(n);
  (Mx.define((i, j) => M((a[i] ^ a[j]).bitCnt % 3 == 0),
	   n, n)^^(k - 1))[]
    .sum
    .writeln;
}
ulong bitCnt(long x)
{
  ulong cnt = 0;
  while(x) {cnt += x & 1; x>>=1;}
  return cnt;
}
struct Mat(T, size_t dimension, alias allocator)
{
  typeof(allocator) _allocatedNode;
  T[] _slice;
  size_t[dimension] _sizes;
  size_t dim(size_t i) {return _sizes[i];}
  size_t[dimension] _indexer;
  static if (dimension == 2)
    static Mat!(T, dimension, allocator) define(S...)(T delegate(size_t, size_t) F, S sizes)
    {
      auto res = Mat!(T, dimension, allocator)(sizes);
      with(res)
      foreach(i; 0 .. sizes[0])
	foreach(j; 0 .. sizes[1])
	  res[i, j] = F(i, j);
      return res;
    }
  this(S...)(S sizes)
  {
    static assert(sizes.length == dimension);
    _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];
    _allocatedNode = allocator.alloc;
    _slice = _allocatedNode.allocated[0 .. requiredSize];
  }
  void free()
  {
    allocator.free(_allocatedNode);
  }
  ref auto opIndex()
  {
    return _slice[];
  }
  ref auto opIndex(I...)(I i)
  {
    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
      {
	static assert(0);
	version(none)
	  {
	    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, allocator)(basePortion, remSizes);
	  }
      }
  }
  static if (dimension == 2)
    {
      auto identity()
      {
	debug assert(dim(0) == dim(1));
	auto n = dim(0);
	return Mat!(T, 2, allocator).define((i, j) => T(i == j), n, n);
      }
      bool canMultiply(alias alloc)(Mat!(T, 2, alloc) b)
      {
	return this.dim(1) == b.dim(0);
      }
      version(none) auto opBinary(string op)(Mat!(T, 2, allocator) 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] += this[i, k] * b[k, j];
	    return res;
	  }

      auto opOpAssign(string op)(Mat!(T, 2, allocator) b)
	if (op == "*")
	  {
	    static T[100 * 100] resBuff;
	    debug assert(canMultiply(b));
	    auto res = Mat!(T, 2, allocator)(this.dim(0), b.dim(1));
	    res[][] = T(0);
	    foreach(i; 0 .. res.dim(0))
	      foreach(k; 0 .. this.dim(1))
		foreach(j; 0 .. res.dim(1))
		  res[i, j] += this[i, k] * b[k, j];
	    this[][] = res[][];
	    res.free;
	    return this;
	  }

      auto opBinary(string op)(ulong exp)
	if (op == "^^")
	  {
	    return this.pow(identity, exp);
	  }
      mixin interiorBinPow;
    }
}

struct Mod(T, long mod)
{
  alias This = Mod!(T, mod);
  T rep;
  string toString()
  {
    return to!string(rep);
  }
  static auto makeSafe(T t)
  {
    if (t >= 0) return Mod!(T, mod)(t % mod);
    return Mod!(T, mod)(t % mod + mod);
  }
  auto opBinary(string op)(This b)
  {
    pragma(inline, true);
    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((rep * b.rep)%mod);
      }
  }
  auto opOpAssign(string op)(This b)
  {
    pragma(inline, true);
    static if (op == "+")
      {
	this.rep += b.rep;
	if (this.rep >= mod) this.rep -= mod;
      }
    else static if (op == "-")
      {
	this.rep -= b.rep;
	if (this.rep < 0) this.rep += mod;
      }
    else static if (op == "*")
      {
	this.rep *= b.rep;
	this.rep %= mod;
      }
  }
}

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

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

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

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

import std.stdio;
import std.uni;
import std.conv;
import std.container;
import std.functional;
import std.algorithm;
import std.array;
import std.typecons;
import std.range;
import std.numeric;
import core.memory;
enum mod = 1_000_000_000 + 7;

alias M = Mod!(long, mod);
alias Mx = StaticMat!(M, 100, 100);

void main(string[] args)
{
  auto n = next!int;
  auto k = next!long;
  auto a = next!long(n);
  auto values = Mx.def(n, n, (i, j) => M((a[i] ^ a[j]).bitCnt % 3 == 0))^^(k - 1);
  auto sum = M(0);
  foreach(i; 0 .. n)
    foreach(j; 0 .. n)
      sum += values[i][j];
  return sum.writeln;
}
ulong bitCnt(long x)
{
  pragma(inline, true);
  ulong cnt = 0;
  while(x) {cnt += x & 1; x>>=1;}
  return cnt;
}
struct StaticMat(T, maxSizes...)
{
  enum dimension = maxSizes.length;
  size_t[dimension] size;
  this(S...)(S s)
    {
      static assert(s.length == dimension);
      size[] = [s];
    }
  StaticArray!(T, maxSizes) at;
  alias at this;
  static if (dimension == 2)
    {
      static auto def(size_t s0, size_t s1, T delegate(size_t, size_t) elem)
      {
	auto mat = StaticMat!(T, maxSizes)(s0, s1);
	foreach(i; 0 .. s0)
	  foreach(j; 0 .. s1)
	    mat[i][j] = elem(i, j);
	return mat;
      }
      auto identity()
      {
	return StaticMat!(T, maxSizes).def(size[0], size[1], (i, j) => T(cast(int)i == j));
      }
      auto opOpAssign(string op)(StaticMat!(T, maxSizes) b)
	if (op == "*")
      {
	debug assert(this.size[1] == b.size[0]);
	auto n = this.size[0];
	auto m = this.size[1];
	auto r = b.size[1];
	auto res = StaticMat!(T, maxSizes)(n, r);
	foreach(i; 0 .. n) foreach(j; 0 .. r) res[i][j] = T(0);
	foreach(i; 0 .. n)
	  foreach(k; 0 .. m)
	    foreach(j; 0 .. r)
	      res[i][j] += this[i][k] * b[k][j];
	this.size = res.size;
	foreach(i; 0 .. n) foreach(j; 0 .. r) this[i][j] = res[i][j];
      }
      auto opBinary(string op)(ulong exp)
	if (op == "^^")
	  {
	    pragma(inline, true);
	    return this.pow(identity, exp);
	  }
      mixin interiorBinPow;
    }
}

template StaticArray(T, sizes...)
{
  static if (sizes.length == 1)
    alias StaticArray = T[sizes[0]];
  else
    alias StaticArray = StaticArray!(T, sizes[1 .. $])[sizes[0]];
}

struct Mod(T, long mod)
{
  alias This = Mod!(T, mod);
  T rep;
  string toString()
  {
    return to!string(rep);
  }
  static auto makeSafe(T t)
  {
    if (t >= 0) return Mod!(T, mod)(t % mod);
    return Mod!(T, mod)(t % mod + mod);
  }
  auto opBinary(string op)(This b)
  {
    pragma(inline, true);
    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((rep * b.rep)%mod);
      }
  }
  auto opOpAssign(string op)(This b)
  {
    pragma(inline, true);
    static if (op == "+")
      {
	this.rep += b.rep;
	if (this.rep >= mod) this.rep -= mod;
      }
    else static if (op == "-")
      {
	this.rep -= b.rep;
	if (this.rep < 0) this.rep += mod;
      }
    else static if (op == "*")
      {
	this.rep *= b.rep;
	this.rep %= mod;
      }
  }
}

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

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

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

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

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

enum mod = 1_000_000_000 + 7;
void mul(T, size_t s)(out T[s][s] res, ref T[s][s] a, ref T[s][s] b)
{
  foreach(i; 0 .. s) foreach(j; 0 .. s) res[i][j] = T(0);
  foreach(i; 0 .. s)
    foreach(k; 0 .. s)
      foreach(j; 0 .. s)
	res[i][j] = res[i][j] + a[i][k] * b[k][j];
}

void main(string[] args)
{
  alias M = Mod!(long, mod);
  auto n = next!int;
  auto k = next!long;
  auto a = next!long(n);
  debug writeln(n, k, a);
  M[100][100] pow, tmp, res;
  foreach(i, ai; a)
    foreach(j, aj; a)
      pow[i][j] = M((ai ^ aj).bitCnt % 3 == 0);
  foreach(i; 0 .. n) res[i][i] = M(1);
  k--;
  while(k)
    {
      if (k & 1)
	{
	  mul(tmp, res, pow);
	  res = tmp;
	}
      mul(tmp, pow, pow);
      pow = tmp;
      k >>= 1;
    }
  auto sum = M(0);
  foreach(i; 0 .. n)
    foreach(j; 0 .. n)
      sum = sum + res[i][j];
  sum.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[] _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)
  {
    _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];
  }
  version(none) 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()
  {
    return _slice[];
  }
  ref auto opIndex(I...)(I i)
  {
    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)
    {
      static bool identitySet = false;
      static Mat!(T, 2) _identity;
      static T[100 * 100] _identityBuff;
      auto identity()
      {
	if (identitySet) return _identity;
	debug assert(dim(0) == dim(1));
	auto n = dim(0);
	_identity = Mat!(T, 2)(_identityBuff, [n, n]);
	foreach(k; 0 .. n)
	  _identity[k, k] = T(1);
	identitySet = true;
	return _identity;
      }
      bool canMultiply(Mat!(T, 2) b)
      {
	return this.dim(1) == b.dim(0);
      }
      version(none) 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 opOpAssign(string op)(Mat!(T, 2) b)
	if (op == "*")
	  {
	    static T[100 * 100] resBuff;
	    debug assert(canMultiply(b));
	    auto res = Mat!(T, 2)(resBuff, [this.dim(0), b.dim(1)]);
	    res[][] = T(0);
	    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];
	    this[][] = res[][];
	    return this;
	  }

      auto opBinary(string op)(ulong exp)
	if (op == "^^")
	  {
	    return this.pow(identity, exp);
	  }
      mixin interiorBinPow;
    }
}

struct Mod(T, long mod)
{
  alias This = Mod!(T, mod);
  T rep;
  string toString()
  {
    return to!string(rep);
  }
  debug invariant
  {
    assert(rep >= 0 && rep < mod);
  }
  auto opBinary(string op)(This b)
  {
    pragma(inline, true);
    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((rep * b.rep)%mod);
      }
  }
}

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

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

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

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

import std.stdio;
import std.uni;
import std.conv;
import std.container;
import std.functional;
import std.algorithm;
import std.array;
import std.typecons;
import std.range;
import std.numeric;
import core.memory;
enum mod = 1_000_000_000 + 7;

alias M = Mod!(long, mod);
alias Mx = Mat!(M, 2);

void main(string[] args)
{
  auto n = next!int;
  auto k = next!long;
  auto a = next!long(n);
  auto values = (Mx.define((i, j) => M((a[i] ^ a[j]).bitCnt % 3 == 0),n, n)^^(k - 1))[];
  values.sum.writeln;
}
ulong bitCnt(long x)
{
  ulong cnt = 0;
  while(x) {cnt += x & 1; x>>=1;}
  return cnt;
}
struct Mat(T, size_t dimension)
{
  T[] _slice;
  size_t[dimension] _sizes; size_t dim(size_t i) {return _sizes[i];}
  size_t[dimension] _indexer;
  static if (dimension == 2)
    static Mat!(T, dimension) define(S...)(T delegate(size_t, size_t) F, S sizes)
    {
      auto res = Mat!(T, dimension)(sizes);
      with(res)
      foreach(i; 0 .. sizes[0])
	foreach(j; 0 .. sizes[1])
	  res[i, j] = F(i, j);
      return res;
    }
  this(S...)(S sizes)
  {
    static assert(sizes.length == dimension);
    _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];
    _slice = new T[](requiredSize);
  }
  ref auto opIndex()
  {
    return _slice[];
  }
  ref auto opIndex(I...)(I i)
  {
    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
      {
	static assert(0);
	version(none)
	  {
	    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);
	return Mat!(T, 2).define((i, j) => T(i == j), n, n);
      }
      bool canMultiply(Mat!(T, 2) b)
      {
	return this.dim(1) == b.dim(0);
      }
      version(none) 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] += this[i, k] * b[k, j];
	    return res;
	  }

      auto opOpAssign(string op)(Mat!(T, 2) b)
	if (op == "*")
	  {
	    static T[100 * 100] resBuff;
	    debug assert(canMultiply(b));
	    auto res = Mat!(T, 2)(this.dim(0), b.dim(1));
	    res[][] = T(0);
	    foreach(i; 0 .. res.dim(0))
	      foreach(k; 0 .. this.dim(1))
		foreach(j; 0 .. res.dim(1))
		  res[i, j] += this[i, k] * b[k, j];
	    this[][] = res[][];
	    return this;
	  }

      auto opBinary(string op)(ulong exp)
	if (op == "^^")
	  {
	    return this.pow(identity, exp);
	  }
      mixin interiorBinPow;
    }
}

struct Mod(T, long mod)
{
  alias This = Mod!(T, mod);
  T rep;
  string toString()
  {
    return to!string(rep);
  }
  static auto makeSafe(T t)
  {
    if (t >= 0) return Mod!(T, mod)(t % mod);
    return Mod!(T, mod)(t % mod + mod);
  }
  auto opBinary(string op)(This b)
  {
    pragma(inline, true);
    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((rep * b.rep)%mod);
      }
  }
  auto opOpAssign(string op)(This b)
  {
    pragma(inline, true);
    static if (op == "+")
      {
	this.rep += b.rep;
	if (this.rep >= mod) this.rep -= mod;
      }
    else static if (op == "-")
      {
	this.rep -= b.rep;
	if (this.rep < 0) this.rep += mod;
      }
    else static if (op == "*")
      {
	this.rep *= b.rep;
	this.rep %= mod;
      }
  }
}

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

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

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

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

import std.stdio;
import std.uni;
import std.conv;
import std.container;
import std.functional;
import std.algorithm;
import std.array;
import std.typecons;
import std.range;
import std.numeric;
import core.memory;
enum mod = 1_000_000_000 + 7;
class FreeList(T)
{
  T allocated;
  FreeList!T next = null;
  this(FreeList!T next)
  {
    this.next = next;
  }
}
long totalUse = 0;
FreeList!T alloc(T)(ref FreeList!T freeList)
{
  if (freeList is null)
    {
      totalUse++;
      return new FreeList!T(null);
    }
  else
    {
      auto ret = freeList;
      freeList = freeList.next;
      ret.next = null;
      return ret;
    }
}
void free(T)(ref FreeList!T freeList, FreeList!T t)
{
  debug assert(t.next is null);
  t.next = freeList;
  freeList = t;
}

alias M = Mod!(long, mod);
FreeList!(M[100 * 100]) mAlloc;
alias Mx = Mat!(M, 2, mAlloc);

void main(string[] args)
{
  auto n = next!int;
  auto k = next!long;
  auto a = next!long(n);
  (Mx.define((i, j) => M((a[i] ^ a[j]).bitCnt % 3 == 0),
	   n, n)^^(k - 1))[]
    .sum
    .writeln;
  assert(totalUse <= 3);
}
ulong bitCnt(long x)
{
  ulong cnt = 0;
  while(x) {cnt += x & 1; x>>=1;}
  return cnt;
}
struct Mat(T, size_t dimension, alias allocator)
{
  typeof(allocator) _allocatedNode;
  T[] _slice;
  size_t[dimension] _sizes;
  size_t dim(size_t i) {return _sizes[i];}
  size_t[dimension] _indexer;
  static if (dimension == 2)
    static Mat!(T, dimension, allocator) define(S...)(T delegate(size_t, size_t) F, S sizes)
    {
      auto res = Mat!(T, dimension, allocator)(sizes);
      with(res)
      foreach(i; 0 .. sizes[0])
	foreach(j; 0 .. sizes[1])
	  res[i, j] = F(i, j);
      return res;
    }
  this(S...)(S sizes)
  {
    static assert(sizes.length == dimension);
    _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];
    _allocatedNode = allocator.alloc;
    _slice = _allocatedNode.allocated[0 .. requiredSize];
  }
  void free()
  {
    allocator.free(_allocatedNode);
  }
  ref auto opIndex()
  {
    return _slice[];
  }
  ref auto opIndex(I...)(I i)
  {
    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
      {
	static assert(0);
	version(none)
	  {
	    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, allocator)(basePortion, remSizes);
	  }
      }
  }
  static if (dimension == 2)
    {
      auto identity()
      {
	debug assert(dim(0) == dim(1));
	auto n = dim(0);
	return Mat!(T, 2, allocator).define((i, j) => T(i == j), n, n);
      }
      bool canMultiply(alias alloc)(Mat!(T, 2, alloc) b)
      {
	return this.dim(1) == b.dim(0);
      }
      version(none) auto opBinary(string op)(Mat!(T, 2, allocator) 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] += this[i, k] * b[k, j];
	    return res;
	  }

      auto opOpAssign(string op)(Mat!(T, 2, allocator) b)
	if (op == "*")
	  {
	    static T[100 * 100] resBuff;
	    debug assert(canMultiply(b));
	    auto res = Mat!(T, 2, allocator)(this.dim(0), b.dim(1));
	    res[][] = T(0);
	    foreach(i; 0 .. res.dim(0))
	      foreach(k; 0 .. this.dim(1))
		foreach(j; 0 .. res.dim(1))
		  res[i, j] += this[i, k] * b[k, j];
	    this[][] = res[][];
	    res.free;
	    return this;
	  }

      auto opBinary(string op)(ulong exp)
	if (op == "^^")
	  {
	    return this.pow(identity, exp);
	  }
      mixin interiorBinPow;
    }
}

struct Mod(T, long mod)
{
  alias This = Mod!(T, mod);
  T rep;
  string toString()
  {
    return to!string(rep);
  }
  static auto makeSafe(T t)
  {
    if (t >= 0) return Mod!(T, mod)(t % mod);
    return Mod!(T, mod)(t % mod + mod);
  }
  auto opBinary(string op)(This b)
  {
    pragma(inline, true);
    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((rep * b.rep)%mod);
      }
  }
  auto opOpAssign(string op)(This b)
  {
    pragma(inline, true);
    static if (op == "+")
      {
	this.rep += b.rep;
	if (this.rep >= mod) this.rep -= mod;
      }
    else static if (op == "-")
      {
	this.rep -= b.rep;
	if (this.rep < 0) this.rep += mod;
      }
    else static if (op == "*")
      {
	this.rep *= b.rep;
	this.rep %= mod;
      }
  }
}

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

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

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

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

import std.stdio;
import std.uni;
import std.conv;
import std.container;
import std.functional;
import std.algorithm;
import std.array;
import std.typecons;
import std.range;
import std.numeric;
import core.memory;
enum mod = 1_000_000_000 + 7;
class FreeList(T)
{
  T allocated;
  FreeList!T next = null;
  size_t size;
  this(FreeList!T next)
  {
    this.next = next;
    this.size = 1 + (next is null? 0 : next.size);
    assert(this.size <= 4);
  }
}
FreeList!T alloc(T)(ref FreeList!T freeList)
{
  if (freeList is null)
    {
      return new FreeList!T(null);
    }
  else
    {
      auto ret = freeList;
      freeList = freeList.next;
      ret.next = null;
      return ret;
    }
}
void free(T)(ref FreeList!T freeList, FreeList!T t)
{
  debug assert(t.next is null);
  t.next = freeList;
  freeList = t;
}

alias M = Mod!(long, mod);
FreeList!(M[100 * 100]) mAlloc;
alias Mx = Mat!(M, 2, mAlloc);

void main(string[] args)
{
  auto n = next!int;
  auto k = next!long;
  auto a = next!long(n);
  (Mx.define((i, j) => M((a[i] ^ a[j]).bitCnt % 3 == 0),
	   n, n)^^(k - 1))[]
    .sum
    .writeln;
}
ulong bitCnt(long x)
{
  ulong cnt = 0;
  while(x) {cnt += x & 1; x>>=1;}
  return cnt;
}
struct Mat(T, size_t dimension, alias allocator)
{
  typeof(allocator) _allocatedNode;
  T[] _slice;
  size_t[dimension] _sizes;
  size_t dim(size_t i) {return _sizes[i];}
  size_t[dimension] _indexer;
  static if (dimension == 2)
    static Mat!(T, dimension, allocator) define(S...)(T delegate(size_t, size_t) F, S sizes)
    {
      auto res = Mat!(T, dimension, allocator)(sizes);
      with(res)
      foreach(i; 0 .. sizes[0])
	foreach(j; 0 .. sizes[1])
	  res[i, j] = F(i, j);
      return res;
    }
  this(S...)(S sizes)
  {
    static assert(sizes.length == dimension);
    _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];
    _allocatedNode = allocator.alloc;
    _slice = _allocatedNode.allocated[0 .. requiredSize];
  }
  void free()
  {
    allocator.free(_allocatedNode);
  }
  ref auto opIndex()
  {
    return _slice[];
  }
  ref auto opIndex(I...)(I i)
  {
    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
      {
	static assert(0);
	version(none)
	  {
	    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, allocator)(basePortion, remSizes);
	  }
      }
  }
  static if (dimension == 2)
    {
      auto identity()
      {
	debug assert(dim(0) == dim(1));
	auto n = dim(0);
	return Mat!(T, 2, allocator).define((i, j) => T(i == j), n, n);
      }
      bool canMultiply(alias alloc)(Mat!(T, 2, alloc) b)
      {
	return this.dim(1) == b.dim(0);
      }
      version(none) auto opBinary(string op)(Mat!(T, 2, allocator) 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] += this[i, k] * b[k, j];
	    return res;
	  }

      auto opOpAssign(string op)(Mat!(T, 2, allocator) b)
	if (op == "*")
	  {
	    static T[100 * 100] resBuff;
	    debug assert(canMultiply(b));
	    auto res = Mat!(T, 2, allocator)(this.dim(0), b.dim(1));
	    res[][] = T(0);
	    foreach(i; 0 .. res.dim(0))
	      foreach(k; 0 .. this.dim(1))
		foreach(j; 0 .. res.dim(1))
		  res[i, j] += this[i, k] * b[k, j];
	    this[][] = res[][];
	    res.free;
	    return this;
	  }

      auto opBinary(string op)(ulong exp)
	if (op == "^^")
	  {
	    return this.pow(identity, exp);
	  }
      mixin interiorBinPow;
    }
}

struct Mod(T, long mod)
{
  alias This = Mod!(T, mod);
  T rep;
  string toString()
  {
    return to!string(rep);
  }
  static auto makeSafe(T t)
  {
    if (t >= 0) return Mod!(T, mod)(t % mod);
    return Mod!(T, mod)(t % mod + mod);
  }
  auto opBinary(string op)(This b)
  {
    pragma(inline, true);
    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((rep * b.rep)%mod);
      }
  }
  auto opOpAssign(string op)(This b)
  {
    pragma(inline, true);
    static if (op == "+")
      {
	this.rep += b.rep;
	if (this.rep >= mod) this.rep -= mod;
      }
    else static if (op == "-")
      {
	this.rep -= b.rep;
	if (this.rep < 0) this.rep += mod;
      }
    else static if (op == "*")
      {
	this.rep *= b.rep;
	this.rep %= mod;
      }
  }
}

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

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

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

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

import std.stdio;
import std.uni;
import std.conv;
import std.container;
import std.functional;
import std.algorithm;
import std.array;
import std.typecons;
import std.range;
import std.numeric;
import core.memory;
enum mod = 1_000_000_000 + 7;
class FreeList(T)
{
  T allocated;
  FreeList!T next = null;
  this(FreeList!T next)
  {
    this.next = next;
  }
}
FreeList!T alloc(T)(ref FreeList!T freeList)
{
  if (freeList is null)
    {
      return new FreeList!T(null);
    }
  else
    {
      auto ret = freeList;
      freeList = freeList.next;
      ret.next = null;
      return ret;
    }
}
void free(T)(ref FreeList!T freeList, FreeList!T t)
{
  debug assert(t.next is null);
  t.next = freeList;
  freeList = t;
}

alias M = Mod!(long, mod);
FreeList!(M[100 * 100]) mAlloc;
alias Mx = Mat!(M, 2, mAlloc);

void main(string[] args)
{
  auto n = next!int;
  auto k = next!long;
  auto a = next!long(n);
  (Mx.make((i, j) => M((a[i] ^ a[j]).bitCnt % 3 == 0),
	   n, n)^^(k - 1))[]
    .sum
    .writeln;
}
ulong bitCnt(long x)
{
  ulong cnt = 0;
  while(x) {cnt += x & 1; x>>=1;}
  return cnt;
}
struct Mat(T, size_t dimension, alias allocator)
{
  typeof(allocator) _allocatedNode;
  T[] _slice;
  size_t[dimension] _sizes;
  size_t dim(size_t i) {return _sizes[i];}
  size_t[dimension] _indexer;
  static if (dimension == 2)
    static Mat!(T, dimension, allocator) make(S...)(T delegate(size_t, size_t) F, S sizes)
    {
      auto res = Mat!(T, dimension, allocator)(sizes);
      with(res)
      foreach(i; 0 .. sizes[0])
	foreach(j; 0 .. sizes[1])
	  res[i, j] = F(i, j);
      return res;
    }
  this(S...)(S sizes)
  {
    static assert(sizes.length == dimension);
    _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];
    _allocatedNode = allocator.alloc;
    _slice = _allocatedNode.allocated[0 .. requiredSize];
  }
  void free()
  {
    allocator.free(_allocatedNode);
  }
  ref auto opIndex()
  {
    return _slice[];
  }
  ref auto opIndex(I...)(I i)
  {
    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
      {
	static assert(0);
	version(none)
	  {
	    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, allocator)(basePortion, remSizes);
	  }
      }
  }
  static if (dimension == 2)
    {
      auto identity()
      {
	debug assert(dim(0) == dim(1));
	auto n = dim(0);
	auto _identity = Mat!(T, 2, allocator)(n, n);
	foreach(i; 0 .. n)
	  foreach(j; 0 .. n)
	    _identity[i, j] = T(i == j);
	return _identity;
      }
      bool canMultiply(alias alloc)(Mat!(T, 2, alloc) b)
      {
	return this.dim(1) == b.dim(0);
      }
      version(none) auto opBinary(string op)(Mat!(T, 2, allocator) 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] += this[i, k] * b[k, j];
	    return res;
	  }

      auto opOpAssign(string op)(Mat!(T, 2, allocator) b)
	if (op == "*")
	  {
	    static T[100 * 100] resBuff;
	    debug assert(canMultiply(b));
	    auto res = Mat!(T, 2, allocator)(this.dim(0), b.dim(1));
	    res[][] = T(0);
	    foreach(i; 0 .. res.dim(0))
	      foreach(k; 0 .. this.dim(1))
		foreach(j; 0 .. res.dim(1))
		  res[i, j] += this[i, k] * b[k, j];
	    this[][] = res[][];
	    res.free;
	    return this;
	  }

      auto opBinary(string op)(ulong exp)
	if (op == "^^")
	  {
	    return this.pow(identity, exp);
	  }
      mixin interiorBinPow;
    }
}

struct Mod(T, long mod)
{
  alias This = Mod!(T, mod);
  T rep;
  string toString()
  {
    return to!string(rep);
  }
  static auto makeSafe(T t)
  {
    if (t >= 0) return Mod!(T, mod)(t % mod);
    return Mod!(T, mod)(t % mod + mod);
  }
  auto opBinary(string op)(This b)
  {
    pragma(inline, true);
    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((rep * b.rep)%mod);
      }
  }
  auto opOpAssign(string op)(This b)
  {
    pragma(inline, true);
    static if (op == "+")
      {
	this.rep += b.rep;
	if (this.rep >= mod) this.rep -= mod;
      }
    else static if (op == "-")
      {
	this.rep -= b.rep;
	if (this.rep < 0) this.rep += mod;
      }
    else static if (op == "*")
      {
	this.rep *= b.rep;
	this.rep %= mod;
      }
  }
}

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

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

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

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

import std.stdio;
import std.uni;
import std.conv;
import std.container;
import std.functional;
import std.algorithm;
import std.array;
import std.typecons;
import std.range;
import std.numeric;
import core.memory;
enum mod = 1_000_000_000 + 7;
void main(string[] args)
{
  GC.disable;
  alias M = Mod!(long, mod);
  alias Mx = Mat!(M, 2);
  M[100 * 100] basePow;
  long[100] baseA;
  auto n = next!int;
  auto k = next!long;
  auto a = Arr!long(baseA, [n]);
  foreach(ref ai; a[]) ai = next!long;
  Mx mx = Mx(basePow, [n, n]);
  foreach(i, ai; a)
    foreach(j, aj; a)
      mx[i, j] = M((ai ^ aj).bitCnt % 3 == 0);
  (mx^^(k-1))[].sum.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[] _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)
  {
    _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];
  }
  version(none) 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()
  {
    return _slice[];
  }
  ref auto opIndex(I...)(I i)
  {
    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)
    {
      static bool identitySet = false;
      static Mat!(T, 2) _identity;
      static T[100 * 100] _identityBuff;
      auto identity()
      {
	if (identitySet) return _identity;
	debug assert(dim(0) == dim(1));
	auto n = dim(0);
	_identity = Mat!(T, 2)(_identityBuff, [n, n]);
	foreach(k; 0 .. n)
	  _identity[k, k] = T(1);
	identitySet = true;
	return _identity;
      }
      bool canMultiply(Mat!(T, 2) b)
      {
	return this.dim(1) == b.dim(0);
      }
      version(none) 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] += this[i, k] * b[k, j];
	    return res;
	  }

      auto opOpAssign(string op)(Mat!(T, 2) b)
	if (op == "*")
	  {
	    static T[100 * 100] resBuff;
	    debug assert(canMultiply(b));
	    auto res = Mat!(T, 2)(resBuff, [this.dim(0), b.dim(1)]);
	    res[][] = T(0);
	    foreach(i; 0 .. res.dim(0))
	      foreach(k; 0 .. this.dim(1))
		foreach(j; 0 .. res.dim(1))
		  res[i, j] += this[i, k] * b[k, j];
	    this[][] = res[][];
	    return this;
	  }

      auto opBinary(string op)(ulong exp)
	if (op == "^^")
	  {
	    return this.pow(identity, exp);
	  }
      mixin interiorBinPow;
    }
}

struct Mod(T, long mod)
{
  alias This = Mod!(T, mod);
  T rep;
  string toString()
  {
    return to!string(rep);
  }
  debug invariant
  {
    assert(rep >= 0 && rep < mod);
  }
  auto opBinary(string op)(This b)
  {
    pragma(inline, true);
    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((rep * b.rep)%mod);
      }
  }
  auto opOpAssign(string op)(This b)
  {
    pragma(inline, true);
    static if (op == "+")
      {
	this.rep += b.rep;
	if (this.rep >= mod) this.rep -= mod;
      }
    else static if (op == "-")
      {
	this.rep -= b.rep;
	if (this.rep < 0) this.rep += mod;
      }
    else static if (op == "*")
      {
	this.rep *= b.rep;
	this.rep %= mod;
      }
  }
}

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

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

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

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

import std.stdio;
import std.uni;
import std.conv;
import std.container;
import std.functional;
import std.algorithm;
import std.array;
import std.typecons;
import std.range;
import std.numeric;
import core.memory;
enum mod = 1_000_000_000 + 7;
class FreeList(T)
{
  T allocated;
  FreeList!T next = null;
  this(FreeList!T next)
  {
    this.next = next;
  }
}
long totalUse = 0;
FreeList!T alloc(T)(ref FreeList!T freeList)
{
  if (freeList is null)
    {
      totalUse++;
      return new FreeList!T(null);
    }
  else
    {
      auto ret = freeList;
      freeList = freeList.next;
      ret.next = null;
      return ret;
    }
}
void free(T)(ref FreeList!T freeList, FreeList!T t)
{
  debug assert(t.next is null);
  t.next = freeList;
  freeList = t;
}

alias M = Mod!(long, mod);
FreeList!(M[100 * 100]) mAlloc;
alias Mx = Mat!(M, 2, mAlloc);

void main(string[] args)
{
  auto n = next!int;
  auto k = next!long;
  auto a = next!long(n);
  (Mx.define((i, j) => M((a[i] ^ a[j]).bitCnt % 3 == 0),
	   n, n)^^(k - 1))[]
    .sum
    .writeln;
  assert(totalUse <= 2);
}
ulong bitCnt(long x)
{
  ulong cnt = 0;
  while(x) {cnt += x & 1; x>>=1;}
  return cnt;
}
struct Mat(T, size_t dimension, alias allocator)
{
  typeof(allocator) _allocatedNode;
  T[] _slice;
  size_t[dimension] _sizes;
  size_t dim(size_t i) {return _sizes[i];}
  size_t[dimension] _indexer;
  static if (dimension == 2)
    static Mat!(T, dimension, allocator) define(S...)(T delegate(size_t, size_t) F, S sizes)
    {
      auto res = Mat!(T, dimension, allocator)(sizes);
      with(res)
      foreach(i; 0 .. sizes[0])
	foreach(j; 0 .. sizes[1])
	  res[i, j] = F(i, j);
      return res;
    }
  this(S...)(S sizes)
  {
    static assert(sizes.length == dimension);
    _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];
    _allocatedNode = allocator.alloc;
    _slice = _allocatedNode.allocated[0 .. requiredSize];
  }
  void free()
  {
    allocator.free(_allocatedNode);
  }
  ref auto opIndex()
  {
    return _slice[];
  }
  ref auto opIndex(I...)(I i)
  {
    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
      {
	static assert(0);
	version(none)
	  {
	    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, allocator)(basePortion, remSizes);
	  }
      }
  }
  static if (dimension == 2)
    {
      auto identity()
      {
	debug assert(dim(0) == dim(1));
	auto n = dim(0);
	return Mat!(T, 2, allocator).define((i, j) => T(i == j), n, n);
      }
      bool canMultiply(alias alloc)(Mat!(T, 2, alloc) b)
      {
	return this.dim(1) == b.dim(0);
      }
      version(none) auto opBinary(string op)(Mat!(T, 2, allocator) 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] += this[i, k] * b[k, j];
	    return res;
	  }

      auto opOpAssign(string op)(Mat!(T, 2, allocator) b)
	if (op == "*")
	  {
	    static T[100 * 100] resBuff;
	    debug assert(canMultiply(b));
	    auto res = Mat!(T, 2, allocator)(this.dim(0), b.dim(1));
	    res[][] = T(0);
	    foreach(i; 0 .. res.dim(0))
	      foreach(k; 0 .. this.dim(1))
		foreach(j; 0 .. res.dim(1))
		  res[i, j] += this[i, k] * b[k, j];
	    this[][] = res[][];
	    res.free;
	    return this;
	  }

      auto opBinary(string op)(ulong exp)
	if (op == "^^")
	  {
	    return this.pow(identity, exp);
	  }
      mixin interiorBinPow;
    }
}

struct Mod(T, long mod)
{
  alias This = Mod!(T, mod);
  T rep;
  string toString()
  {
    return to!string(rep);
  }
  static auto makeSafe(T t)
  {
    if (t >= 0) return Mod!(T, mod)(t % mod);
    return Mod!(T, mod)(t % mod + mod);
  }
  auto opBinary(string op)(This b)
  {
    pragma(inline, true);
    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((rep * b.rep)%mod);
      }
  }
  auto opOpAssign(string op)(This b)
  {
    pragma(inline, true);
    static if (op == "+")
      {
	this.rep += b.rep;
	if (this.rep >= mod) this.rep -= mod;
      }
    else static if (op == "-")
      {
	this.rep -= b.rep;
	if (this.rep < 0) this.rep += mod;
      }
    else static if (op == "*")
      {
	this.rep *= b.rep;
	this.rep %= mod;
      }
  }
}

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

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

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

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

import std.stdio;
import std.uni;
import std.conv;
import std.container;
import std.functional;
import std.algorithm;
import std.array;
import std.typecons;
import std.range;
import std.numeric;
import core.memory;
enum mod = 1_000_000_000 + 7;
class FreeList(T)
{
  T allocated;
  FreeList!T next = null;
  this(FreeList!T next)
  {
    this.next = next;
  }
}
long totalUse = 0;
FreeList!T alloc(T)(ref FreeList!T freeList)
{
  if (freeList is null)
    {
      totalUse++;
      return new FreeList!T(null);
    }
  else
    {
      auto ret = freeList;
      freeList = freeList.next;
      ret.next = null;
      return ret;
    }
}
void free(T)(ref FreeList!T freeList, FreeList!T t)
{
  debug assert(t.next is null);
  t.next = freeList;
  freeList = t;
}

alias M = Mod!(long, mod);
FreeList!(M[100 * 100]) mAlloc;
alias Mx = Mat!(M, 2, mAlloc);

void main(string[] args)
{
  auto n = next!int;
  auto k = next!long;
  auto a = next!long(n);
  auto values = (Mx.define((i, j) => M((a[i] ^ a[j]).bitCnt % 3 == 0),n, n)^^(k - 1))[];
  if(totalUse > 3)
    {
      throw new Error("");
    }
  values.sum.writeln;
}
ulong bitCnt(long x)
{
  ulong cnt = 0;
  while(x) {cnt += x & 1; x>>=1;}
  return cnt;
}
struct Mat(T, size_t dimension, alias allocator)
{
  typeof(allocator) _allocatedNode;
  T[] _slice;
  size_t[dimension] _sizes;
  size_t dim(size_t i) {return _sizes[i];}
  size_t[dimension] _indexer;
  static if (dimension == 2)
    static Mat!(T, dimension, allocator) define(S...)(T delegate(size_t, size_t) F, S sizes)
    {
      auto res = Mat!(T, dimension, allocator)(sizes);
      with(res)
      foreach(i; 0 .. sizes[0])
	foreach(j; 0 .. sizes[1])
	  res[i, j] = F(i, j);
      return res;
    }
  this(S...)(S sizes)
  {
    static assert(sizes.length == dimension);
    _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];
    _allocatedNode = allocator.alloc;
    _slice = _allocatedNode.allocated[0 .. requiredSize];
  }
  void free()
  {
    allocator.free(_allocatedNode);
  }
  ref auto opIndex()
  {
    return _slice[];
  }
  ref auto opIndex(I...)(I i)
  {
    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
      {
	static assert(0);
	version(none)
	  {
	    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, allocator)(basePortion, remSizes);
	  }
      }
  }
  static if (dimension == 2)
    {
      auto identity()
      {
	debug assert(dim(0) == dim(1));
	auto n = dim(0);
	return Mat!(T, 2, allocator).define((i, j) => T(i == j), n, n);
      }
      bool canMultiply(alias alloc)(Mat!(T, 2, alloc) b)
      {
	return this.dim(1) == b.dim(0);
      }
      version(none) auto opBinary(string op)(Mat!(T, 2, allocator) 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] += this[i, k] * b[k, j];
	    return res;
	  }

      auto opOpAssign(string op)(Mat!(T, 2, allocator) b)
	if (op == "*")
	  {
	    static T[100 * 100] resBuff;
	    debug assert(canMultiply(b));
	    auto res = Mat!(T, 2, allocator)(this.dim(0), b.dim(1));
	    res[][] = T(0);
	    foreach(i; 0 .. res.dim(0))
	      foreach(k; 0 .. this.dim(1))
		foreach(j; 0 .. res.dim(1))
		  res[i, j] += this[i, k] * b[k, j];
	    this[][] = res[][];
	    res.free;
	    return this;
	  }

      auto opBinary(string op)(ulong exp)
	if (op == "^^")
	  {
	    return this.pow(identity, exp);
	  }
      mixin interiorBinPow;
    }
}

struct Mod(T, long mod)
{
  alias This = Mod!(T, mod);
  T rep;
  string toString()
  {
    return to!string(rep);
  }
  static auto makeSafe(T t)
  {
    if (t >= 0) return Mod!(T, mod)(t % mod);
    return Mod!(T, mod)(t % mod + mod);
  }
  auto opBinary(string op)(This b)
  {
    pragma(inline, true);
    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((rep * b.rep)%mod);
      }
  }
  auto opOpAssign(string op)(This b)
  {
    pragma(inline, true);
    static if (op == "+")
      {
	this.rep += b.rep;
	if (this.rep >= mod) this.rep -= mod;
      }
    else static if (op == "-")
      {
	this.rep -= b.rep;
	if (this.rep < 0) this.rep += mod;
      }
    else static if (op == "*")
      {
	this.rep *= b.rep;
	this.rep %= mod;
      }
  }
}

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

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

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

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

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

enum mod = 1_000_000_000 + 7;
void mul(T, size_t s)(out T[s][s] res, ref T[s][s] a, ref T[s][s] b)
{
  foreach(i; 0 .. s) foreach(j; 0 .. s) res[i][j] = T(0);
  foreach(i; 0 .. s)
    foreach(k; 0 .. s)
      foreach(j; 0 .. s)
	res[i][j] += a[i][k] * b[k][j];
}

void main(string[] args)
{
  alias M = Mod!(long, mod);
  alias Mx = Mat!(M, 2);
  auto n = next!int;
  auto k = next!long;
  auto a = next!long(n);
  debug writeln(n, k, a);
  M[100 * 100] basePow, baseRes;
  Mx mx = Mx(basePow, [n, n]);
  Mx res = Mx(baseRes, [n, n]);
  foreach(i, ai; a)
    foreach(j, aj; a)
      mx[i, j] = M((ai ^ aj).bitCnt % 3 == 0);
  res = mx^^(k - 1);
  res[].sum.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[] _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)
  {
    _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];
  }
  version(none) 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()
  {
    return _slice[];
  }
  ref auto opIndex(I...)(I i)
  {
    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)
    {
      static bool identitySet = false;
      static Mat!(T, 2) _identity;
      static T[100 * 100] _identityBuff;
      auto identity()
      {
	if (identitySet) return _identity;
	debug assert(dim(0) == dim(1));
	auto n = dim(0);
	_identity = Mat!(T, 2)(_identityBuff, [n, n]);
	foreach(k; 0 .. n)
	  _identity[k, k] = T(1);
	identitySet = true;
	return _identity;
      }
      bool canMultiply(Mat!(T, 2) b)
      {
	return this.dim(1) == b.dim(0);
      }
      version(none) 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] += this[i, k] * b[k, j];
	    return res;
	  }

      auto opOpAssign(string op)(Mat!(T, 2) b)
	if (op == "*")
	  {
	    static T[100 * 100] resBuff;
	    debug assert(canMultiply(b));
	    auto res = Mat!(T, 2)(resBuff, [this.dim(0), b.dim(1)]);
	    res[][] = T(0);
	    foreach(i; 0 .. res.dim(0))
	      foreach(k; 0 .. this.dim(1))
		foreach(j; 0 .. res.dim(1))
		  res[i, j] += this[i, k] * b[k, j];
	    this[][] = res[][];
	    return this;
	  }

      auto opBinary(string op)(ulong exp)
	if (op == "^^")
	  {
	    return this.pow(identity, exp);
	  }
      mixin interiorBinPow;
    }
}

struct Mod(T, long mod)
{
  alias This = Mod!(T, mod);
  T rep;
  string toString()
  {
    return to!string(rep);
  }
  debug invariant
  {
    assert(rep >= 0 && rep < mod);
  }
  auto opBinary(string op)(This b)
  {
    pragma(inline, true);
    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((rep * b.rep)%mod);
      }
  }
  auto opOpAssign(string op)(This b)
  {
    pragma(inline, true);
    static if (op == "+")
      {
	this.rep += b.rep;
	if (this.rep >= mod) this.rep -= mod;
      }
    else static if (op == "-")
      {
	this.rep -= b.rep;
	if (this.rep < 0) this.rep += mod;
      }
    else static if (op == "*")
      {
	this.rep *= b.rep;
	this.rep %= mod;
      }
  }
}

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

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

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

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

import std.stdio;
import std.uni;
import std.conv;
import std.container;
import std.functional;
import std.algorithm;
import std.array;
import std.typecons;
import std.range;
import std.numeric;
import core.memory;
enum mod = 1_000_000_000 + 7;

alias M = Mod!(long, mod);
alias Mx = StaticMat!(M, 100, 100);

void main(string[] args)
{
  auto n = next!int;
  auto k = next!long;
  auto a = next!long(n);
  auto values = Mx.def(n, n, (i, j) => M((a[i] ^ a[j]).bitCnt % 3 == 0))^^(k - 1);
  auto sum = M(0);
  foreach(i; 0 .. n)
    foreach(j; 0 .. n)
      sum += values[i][j];
  return sum.writeln;
}
ulong bitCnt(long x)
{
  pragma(inline, true);
  ulong cnt = 0;
  while(x) {cnt += x & 1; x>>=1;}
  return cnt;
}
struct StaticMat(T, maxSizes...)
{
  enum dimension = maxSizes.length;
  size_t[dimension] size;
  this(S...)(S s)
    {
      static assert(s.length == dimension);
      size[] = [s];
    }
  StaticArray!(T, maxSizes) at;
  alias at this;
  static if (dimension == 2)
    {
      static auto def(size_t s0, size_t s1, T delegate(size_t, size_t) elem)
      {
	auto mat = StaticMat!(T, maxSizes)(s0, s1);
	foreach(i; 0 .. s0)
	  foreach(j; 0 .. s1)
	    mat[i][j] = elem(i, j);
	return mat;
      }
      auto identity()
      {
	return StaticMat!(T, maxSizes).def(size[0], size[1], (i, j) => T(cast(int)i == j));
      }
      auto opOpAssign(string op)(StaticMat!(T, maxSizes) b)
	if (op == "*")
      {
	debug assert(this.size[1] == b.size[0]);
	auto n = this.size[0];
	auto m = this.size[1];
	auto r = b.size[1];
	auto res = StaticMat!(T, maxSizes)(n, r);
	foreach(i; 0 .. n) foreach(j; 0 .. r) res[i][j] = T(0);
	T mul;
	foreach(i; 0 .. n)
	  foreach(k; 0 .. m)
	    if ((mul = this[i][k]) != T(0))
	      foreach(j; 0 .. r)
		res[i][j] += mul * b[k][j];
	this.size = res.size;
	foreach(i; 0 .. n) foreach(j; 0 .. r) this[i][j] = res[i][j];
      }
      auto opBinary(string op)(ulong exp)
	if (op == "^^")
	  {
	    pragma(inline, true);
	    return this.pow(identity, exp);
	  }
      mixin interiorBinPow;
    }
}

template StaticArray(T, sizes...)
{
  static if (sizes.length == 1)
    alias StaticArray = T[sizes[0]];
  else
    alias StaticArray = StaticArray!(T, sizes[1 .. $])[sizes[0]];
}

struct Mod(T, long mod)
{
  alias This = Mod!(T, mod);
  T rep;
  string toString()
  {
    return to!string(rep);
  }
  static auto makeSafe(T t)
  {
    if (t >= 0) return Mod!(T, mod)(t % mod);
    return Mod!(T, mod)(t % mod + mod);
  }
  auto opBinary(string op)(This b)
  {
    pragma(inline, true);
    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((rep * b.rep)%mod);
      }
  }
  auto opOpAssign(string op)(This b)
  {
    pragma(inline, true);
    static if (op == "+")
      {
	this.rep += b.rep;
	if (this.rep >= mod) this.rep -= mod;
      }
    else static if (op == "-")
      {
	this.rep -= b.rep;
	if (this.rep < 0) this.rep += mod;
      }
    else static if (op == "*")
      {
	this.rep *= b.rep;
	this.rep %= mod;
      }
  }
}

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

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

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

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

import std.stdio;
import std.uni;
import std.conv;
import std.container;
import std.functional;
import std.algorithm;
import std.array;
import std.typecons;
import std.range;
import std.numeric;
import core.memory;
enum mod = 1_000_000_000 + 7;

alias M = Mod!(long, mod);
alias Mx = Mat!(M, 2);

void main(string[] args)
{
  auto n = next!int;
  auto k = next!long;
  auto a = next!long(n);
  auto values = (Mx.define((i, j) => M((a[i] ^ a[j]).bitCnt % 3 == 0),n, n)^^(k - 1))[];
  values.sum.writeln;
}
ulong bitCnt(long x)
{
  pragma(inline, true);
  ulong cnt = 0;
  while(x) {cnt += x & 1; x>>=1;}
  return cnt;
}
struct Mat(T, size_t dimension)
{
  T[] _slice;
  size_t[dimension] _sizes; size_t dim(size_t i) {return _sizes[i];}
  size_t[dimension] _indexer;
  static if (dimension == 2)
    static Mat!(T, dimension) define(S...)(T delegate(size_t, size_t) F, S sizes)
    {
      pragma(inline, true);
      auto res = Mat!(T, dimension)(sizes);
      with(res)
      foreach(i; 0 .. sizes[0])
	foreach(j; 0 .. sizes[1])
	  res[i, j] = F(i, j);
      return res;
    }
  this(S...)(S sizes)
  {
    static assert(sizes.length == dimension);
    _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];
    _slice = new T[](requiredSize);
  }
  ref auto opIndex()
  {
    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
      {
	static assert(0);
	version(none)
	  {
	    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()
      {
	pragma(inline, true);
	debug assert(dim(0) == dim(1));
	auto n = dim(0);
	return Mat!(T, 2).define((i, j) => T(i == j), n, n);
      }
      bool canMultiply(Mat!(T, 2) b)
      {
	return this.dim(1) == b.dim(0);
      }
      version(none) auto opBinary(string op)(Mat!(T, 2) b)
	if (op == "*")
	  {
	    pragma(inline, true);
	    debug assert(canMultiply(b));
	    auto res = Mat!(T, 2)([this.dim(0), b.dim(1)]);
	    T mul;
	    foreach(i; 0 .. res.dim(0))
	      foreach(k; 0 .. this.dim(1)) if ((mul = this[i, k]) != T(0))
		foreach(j; 0 .. res.dim(1))
		  res[i, j] += this[i, k] * b[k, j];
	    return res;
	  }

      auto opOpAssign(string op)(Mat!(T, 2) b)
	if (op == "*")
	  {
	    pragma(inline, true);
	    debug assert(canMultiply(b));
	    auto res = Mat!(T, 2)(this.dim(0), b.dim(1));
	    res[][] = T(0);
	    T mul;
	    foreach(i; 0 .. res.dim(0))
	      foreach(k; 0 .. this.dim(1))
		if ((mul = this[i, k]) != T(0))
		  foreach(j; 0 .. res.dim(1))
		    res[i, j] += mul * b[k, j];
	    this[][] = res[][];
	    return this;
	  }

      auto opBinary(string op)(ulong exp)
	if (op == "^^")
	  {
	    pragma(inline, true);
	    return this.pow(identity, exp);
	  }
      mixin interiorBinPow;
    }
}

struct Mod(T, long mod)
{
  alias This = Mod!(T, mod);
  T rep;
  string toString()
  {
    return to!string(rep);
  }
  static auto makeSafe(T t)
  {
    if (t >= 0) return Mod!(T, mod)(t % mod);
    return Mod!(T, mod)(t % mod + mod);
  }
  auto opBinary(string op)(This b)
  {
    pragma(inline, true);
    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((rep * b.rep)%mod);
      }
  }
  auto opOpAssign(string op)(This b)
  {
    pragma(inline, true);
    static if (op == "+")
      {
	this.rep += b.rep;
	if (this.rep >= mod) this.rep -= mod;
      }
    else static if (op == "-")
      {
	this.rep -= b.rep;
	if (this.rep < 0) this.rep += mod;
      }
    else static if (op == "*")
      {
	this.rep *= b.rep;
	this.rep %= mod;
      }
  }
}

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

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

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

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

import std.stdio;
import std.uni;
import std.conv;
import std.container;
import std.functional;
import std.algorithm;
import std.array;
import std.typecons;
import std.range;
import std.numeric;
import core.memory;
enum mod = 1_000_000_000 + 7;
class FreeList(T)
{
  T allocated;
  FreeList!T next = null;
  this(FreeList!T next)
  {
    this.next = next;
  }
}
long totalUse = 0;
FreeList!T alloc(T)(ref FreeList!T freeList)
{
  if (freeList is null)
    {
      totalUse++;
      return new FreeList!T(null);
    }
  else
    {
      auto ret = freeList;
      freeList = freeList.next;
      ret.next = null;
      return ret;
    }
}
void free(T)(ref FreeList!T freeList, FreeList!T t)
{
  debug assert(t.next is null);
  t.next = freeList;
  freeList = t;
}

alias M = Mod!(long, mod);
FreeList!(M[100 * 100]) mAlloc;
alias Mx = Mat!(M, 2, mAlloc);

void main(string[] args)
{
  auto n = next!int;
  auto k = next!long;
  auto a = next!long(n);
  (Mx.define((i, j) => M((a[i] ^ a[j]).bitCnt % 3 == 0),
	   n, n)^^(k - 1))[]
    .sum
    .writeln;
  assert(totalUse <= 5);
}
ulong bitCnt(long x)
{
  ulong cnt = 0;
  while(x) {cnt += x & 1; x>>=1;}
  return cnt;
}
struct Mat(T, size_t dimension, alias allocator)
{
  typeof(allocator) _allocatedNode;
  T[] _slice;
  size_t[dimension] _sizes;
  size_t dim(size_t i) {return _sizes[i];}
  size_t[dimension] _indexer;
  static if (dimension == 2)
    static Mat!(T, dimension, allocator) define(S...)(T delegate(size_t, size_t) F, S sizes)
    {
      auto res = Mat!(T, dimension, allocator)(sizes);
      with(res)
      foreach(i; 0 .. sizes[0])
	foreach(j; 0 .. sizes[1])
	  res[i, j] = F(i, j);
      return res;
    }
  this(S...)(S sizes)
  {
    static assert(sizes.length == dimension);
    _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];
    _allocatedNode = allocator.alloc;
    _slice = _allocatedNode.allocated[0 .. requiredSize];
  }
  void free()
  {
    allocator.free(_allocatedNode);
  }
  ref auto opIndex()
  {
    return _slice[];
  }
  ref auto opIndex(I...)(I i)
  {
    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
      {
	static assert(0);
	version(none)
	  {
	    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, allocator)(basePortion, remSizes);
	  }
      }
  }
  static if (dimension == 2)
    {
      auto identity()
      {
	debug assert(dim(0) == dim(1));
	auto n = dim(0);
	return Mat!(T, 2, allocator).define((i, j) => T(i == j), n, n);
      }
      bool canMultiply(alias alloc)(Mat!(T, 2, alloc) b)
      {
	return this.dim(1) == b.dim(0);
      }
      version(none) auto opBinary(string op)(Mat!(T, 2, allocator) 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] += this[i, k] * b[k, j];
	    return res;
	  }

      auto opOpAssign(string op)(Mat!(T, 2, allocator) b)
	if (op == "*")
	  {
	    static T[100 * 100] resBuff;
	    debug assert(canMultiply(b));
	    auto res = Mat!(T, 2, allocator)(this.dim(0), b.dim(1));
	    res[][] = T(0);
	    foreach(i; 0 .. res.dim(0))
	      foreach(k; 0 .. this.dim(1))
		foreach(j; 0 .. res.dim(1))
		  res[i, j] += this[i, k] * b[k, j];
	    this[][] = res[][];
	    res.free;
	    return this;
	  }

      auto opBinary(string op)(ulong exp)
	if (op == "^^")
	  {
	    return this.pow(identity, exp);
	  }
      mixin interiorBinPow;
    }
}

struct Mod(T, long mod)
{
  alias This = Mod!(T, mod);
  T rep;
  string toString()
  {
    return to!string(rep);
  }
  static auto makeSafe(T t)
  {
    if (t >= 0) return Mod!(T, mod)(t % mod);
    return Mod!(T, mod)(t % mod + mod);
  }
  auto opBinary(string op)(This b)
  {
    pragma(inline, true);
    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((rep * b.rep)%mod);
      }
  }
  auto opOpAssign(string op)(This b)
  {
    pragma(inline, true);
    static if (op == "+")
      {
	this.rep += b.rep;
	if (this.rep >= mod) this.rep -= mod;
      }
    else static if (op == "-")
      {
	this.rep -= b.rep;
	if (this.rep < 0) this.rep += mod;
      }
    else static if (op == "*")
      {
	this.rep *= b.rep;
	this.rep %= mod;
      }
  }
}

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

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

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

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

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

enum mod = 1_000_000_000 + 7;
void mul(T, size_t s)(out T[s][s] res, ref T[s][s] a, ref T[s][s] b)
{
  foreach(i; 0 .. s) foreach(j; 0 .. s) res[i][j] = T(0);
  foreach(i; 0 .. s)
    foreach(k; 0 .. s)
      foreach(j; 0 .. s)
	res[i][j] += a[i][k] * b[k][j];
}

void main(string[] args)
{
  GC.disable;
  alias M = Mod!(long, mod);
  alias Mx = Mat!(M, 2);
  M[100 * 100] basePow;
  long[100] baseA;
  auto n = next!int;
  auto k = next!long;
  auto a = Arr!long(baseA, [n]);
  foreach(ref ai; a[]) ai = next!long;
  Mx mx = Mx(basePow, [n, n]);
  foreach(i, ai; a)
    foreach(j, aj; a)
      mx[i, j] = M((ai ^ aj).bitCnt % 3 == 0);
  (mx^^(k-1))[].sum.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[] _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)
  {
    _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];
  }
  version(none) 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()
  {
    return _slice[];
  }
  ref auto opIndex(I...)(I i)
  {
    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)
    {
      static bool identitySet = false;
      static Mat!(T, 2) _identity;
      static T[100 * 100] _identityBuff;
      auto identity()
      {
	if (identitySet) return _identity;
	debug assert(dim(0) == dim(1));
	auto n = dim(0);
	_identity = Mat!(T, 2)(_identityBuff, [n, n]);
	foreach(k; 0 .. n)
	  _identity[k, k] = T(1);
	identitySet = true;
	return _identity;
      }
      bool canMultiply(Mat!(T, 2) b)
      {
	return this.dim(1) == b.dim(0);
      }
      version(none) 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] += this[i, k] * b[k, j];
	    return res;
	  }

      auto opOpAssign(string op)(Mat!(T, 2) b)
	if (op == "*")
	  {
	    static T[100 * 100] resBuff;
	    debug assert(canMultiply(b));
	    auto res = Mat!(T, 2)(resBuff, [this.dim(0), b.dim(1)]);
	    res[][] = T(0);
	    foreach(i; 0 .. res.dim(0))
	      foreach(k; 0 .. this.dim(1))
		foreach(j; 0 .. res.dim(1))
		  res[i, j] += this[i, k] * b[k, j];
	    this[][] = res[][];
	    return this;
	  }

      auto opBinary(string op)(ulong exp)
	if (op == "^^")
	  {
	    return this.pow(identity, exp);
	  }
      mixin interiorBinPow;
    }
}

struct Mod(T, long mod)
{
  alias This = Mod!(T, mod);
  T rep;
  string toString()
  {
    return to!string(rep);
  }
  debug invariant
  {
    assert(rep >= 0 && rep < mod);
  }
  auto opBinary(string op)(This b)
  {
    pragma(inline, true);
    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((rep * b.rep)%mod);
      }
  }
  auto opOpAssign(string op)(This b)
  {
    pragma(inline, true);
    static if (op == "+")
      {
	this.rep += b.rep;
	if (this.rep >= mod) this.rep -= mod;
      }
    else static if (op == "-")
      {
	this.rep -= b.rep;
	if (this.rep < 0) this.rep += mod;
      }
    else static if (op == "*")
      {
	this.rep *= b.rep;
	this.rep %= mod;
      }
  }
}

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

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

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

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

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

enum mod = 1_000_000_000 + 7;
void mul(T, size_t s)(out T[s][s] res, ref T[s][s] a, ref T[s][s] b)
{
  foreach(i; 0 .. s) foreach(j; 0 .. s) res[i][j] = T(0);
  foreach(i; 0 .. s)
    foreach(k; 0 .. s)
      foreach(j; 0 .. s)
	res[i][j] += a[i][k] * b[k][j];
}

void main(string[] args)
{
  alias M = Mod!(long, mod);
  alias Mx = Mat!(M, 2);
  auto n = next!int;
  auto k = next!long;
  auto a = next!long(n);
  debug writeln(n, k, a);
  M[100 * 100] basePow, baseRes;
  Mx pow = Mx(basePow, [n, n]);
  Mx res = Mx(baseRes, [n, n]);
  foreach(i, ai; a)
    foreach(j, aj; a)
      pow[i, j] = M((ai ^ aj).bitCnt % 3 == 0);
  foreach(i; 0 .. n) res[i][i] = M(1);
  k--;
  while(k)
    {
      if (k & 1)
	res *= pow;
      pow *= pow;
      k >>= 1;
    }
  auto sum = M(0);
  foreach(i; 0 .. n)
    foreach(j; 0 .. n)
      sum += res[i][j];
  sum.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[] _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)
  {
    _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];
  }
  version(none) 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()
  {
    return _slice[];
  }
  ref auto opIndex(I...)(I i)
  {
    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)
    {
      static bool identitySet = false;
      static Mat!(T, 2) _identity;
      static T[100 * 100] _identityBuff;
      auto identity()
      {
	if (identitySet) return _identity;
	debug assert(dim(0) == dim(1));
	auto n = dim(0);
	_identity = Mat!(T, 2)(_identityBuff, [n, n]);
	foreach(k; 0 .. n)
	  _identity[k, k] = T(1);
	identitySet = true;
	return _identity;
      }
      bool canMultiply(Mat!(T, 2) b)
      {
	return this.dim(1) == b.dim(0);
      }
      version(none) 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] += this[i, k] * b[k, j];
	    return res;
	  }

      auto opOpAssign(string op)(Mat!(T, 2) b)
	if (op == "*")
	  {
	    static T[100 * 100] resBuff;
	    debug assert(canMultiply(b));
	    auto res = Mat!(T, 2)(resBuff, [this.dim(0), b.dim(1)]);
	    res[][] = T(0);
	    foreach(i; 0 .. res.dim(0))
	      foreach(k; 0 .. this.dim(1))
		foreach(j; 0 .. res.dim(1))
		  res[i, j] += this[i, k] * b[k, j];
	    this[][] = res[][];
	    return this;
	  }

      auto opBinary(string op)(ulong exp)
	if (op == "^^")
	  {
	    return this.pow(identity, exp);
	  }
      mixin interiorBinPow;
    }
}

struct Mod(T, long mod)
{
  alias This = Mod!(T, mod);
  T rep;
  string toString()
  {
    return to!string(rep);
  }
  debug invariant
  {
    assert(rep >= 0 && rep < mod);
  }
  auto opBinary(string op)(This b)
  {
    pragma(inline, true);
    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((rep * b.rep)%mod);
      }
  }
  auto opOpAssign(string op)(This b)
  {
    pragma(inline, true);
    static if (op == "+")
      {
	this.rep += b.rep;
	if (this.rep >= mod) this.rep -= mod;
      }
    else static if (op == "-")
      {
	this.rep -= b.rep;
	if (this.rep < 0) this.rep += mod;
      }
    else static if (op == "*")
      {
	this.rep *= b.rep;
	this.rep %= mod;
      }
  }
}

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

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

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

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

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

void main(string[] args)
{
  alias M = Mod!(long, 1_000_000_000 + 7);
  alias Mx = Mat!(M, 2);
  inputFile = stdin;
  auto n = next!int;
  auto k = next!long;
  auto a = next!long(n);
  auto mx = Mx([n, n]);
  foreach(i, ai; a)
    foreach(j, aj; a)
      mx[i, j] = M((ai ^ aj).bitCnt % 3 == 0);
  debug foreach(i; 0 .. n) mx[i][].writeln;
  auto pmx = mx^^(k - 1);
  debug foreach(i; 0 .. n) pmx[i][].writeln;
  auto sum = M(0);
  foreach(i; 0 .. n)
    sum = sum + pmx[i][].sum;
  sum.rep.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);
      }
      version(none) 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 opOpAssign(string op)(Mat!(T, 2) b)
	if (op == "*")
	  {
	    static T[100 * 100] resBuff;
	    debug assert(canMultiply(b));
	    auto res = Mat!(T, 2)(resBuff, [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];
	    this[][] = res[][];
	    return this;
	  }

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

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 = 1_000_000_000 + 7;
void mul(T, size_t s)(out T[s][s] res, ref T[s][s] a, ref T[s][s] b)
{
  foreach(i; 0 .. s) foreach(j; 0 .. s) res[i][j] = T(0);
  foreach(i; 0 .. s)
    foreach(k; 0 .. s)
      foreach(j; 0 .. s)
	res[i][j] = (res[i][j] + (a[i][k] * b[k][j])%mod)%mod;
}

void main(string[] args)
{
  alias M = long;
  auto n = next!int;
  auto k = next!long;
  auto a = next!long(n);
  debug writeln(n, k, a);
  M[100][100] pow, tmp, res;
  foreach(i, ai; a)
    foreach(j, aj; a)
      pow[i][j] = M((ai ^ aj).bitCnt % 3 == 0);
  foreach(i; 0 .. n) res[i][i] = M(1);
  k--;
  while(k)
    {
      if (k & 1)
	{
	  mul(tmp, res, pow);
	  res = tmp;
	}
      mul(tmp, pow, pow);
      pow = tmp;
      k >>= 1;
    }
  auto sum = M(0);
  foreach(i; 0 .. n)
    foreach(j; 0 .. n)
      sum = sum + res[i][j];
  sum.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[] _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)
  {
    _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];
  }
  version(none) 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()
  {
    return _slice[];
  }
  ref auto opIndex(I...)(I i)
  {
    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)
    {
      static bool identitySet = false;
      static Mat!(T, 2) _identity;
      static T[100 * 100] _identityBuff;
      auto identity()
      {
	if (identitySet) return _identity;
	debug assert(dim(0) == dim(1));
	auto n = dim(0);
	_identity = Mat!(T, 2)(_identityBuff, [n, n]);
	foreach(k; 0 .. n)
	  _identity[k, k] = T(1);
	identitySet = true;
	return _identity;
      }
      bool canMultiply(Mat!(T, 2) b)
      {
	return this.dim(1) == b.dim(0);
      }
      version(none) 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 opOpAssign(string op)(Mat!(T, 2) b)
	if (op == "*")
	  {
	    static T[100 * 100] resBuff;
	    debug assert(canMultiply(b));
	    auto res = Mat!(T, 2)(resBuff, [this.dim(0), b.dim(1)]);
	    res[][] = T(0);
	    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];
	    this[][] = res[][];
	    return this;
	  }

      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)
  {
    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)
  {
    pragma(inline, true);
    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);
      }
  }
}

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

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

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

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