#define _USE_MATH_DEFINES
#include <assert.h>
#include <math.h>
#include <algorithm>
#include <numeric>
#include <vector>
#include <string>
#include <list>
#include <set>
#include <map>
#include <unordered_set>
#include <unordered_map>
#include <queue>
#include <sstream>
#include <iostream>
#include <fstream>
#include <iomanip>

using namespace std;
typedef long long     ll;
typedef unsigned int  uint;
#define ALL(a)          (a).begin(), (a).end()
#define FOR(i,a,b)      for(int i = a;   i <  (int)(b); ++i)
#define FOR_REV(i,a,b)  for(int i = b-1; i >= (int)(a); --i)
#define FOR_EACH(it,a)  for(remove_reference<decltype(a)>::type::iterator it = (a).begin(); it != (a).end(); ++it)
#define FOR_EACH_REV(it,a) for(remove_reference<decltype(a)>::type::reverse_iterator it = (a).rbegin(); it != (a).rend(); ++it)
#define FOR_EACH_CONST(it,a) for(remove_reference<decltype(a)>::type::const_iterator it = (a).begin(); it != (a).end(); ++it)
#define FOR_EACH_CONST_REV(it,a) for(remove_reference<decltype(a)>::type::const_reverse_iterator it = (a).rbegin(); it != (a).rend(); ++it)
template<class T> inline T   sqr(T v)  { return v * v; }
template<class T> inline int sign(T v) { return v == 0 ? 0 : (v > 0 ? 1 : -1); }
template<class T> inline int get_bit(T v, int bit_index) { return (v >> bit_index) & 1; } //return {0,1}
template<class T> inline T   gcd(T a, T b) { while(b){ T t = b; b   = a % b; a   = t; } return a; }
#define IN_INT(a)            int a;       is >> a;
#define IN_INT2(a,b)         int a,b;     is >> a >> b;
#define IN_INT3(a,b,c)       int a,b,c;   is >> a >> b >> c;
#define IN_INT4(a,b,c,d)     int a,b,c,d; is >> a >> b >> c >> d;
#define IN_LL(a)             ll a;        is >> a;
#define IN_LL2(a,b)          ll a,b;      is >> a >> b;
#define IN_LL3(a,b,c)        ll a,b,c;    is >> a >> b >> c;
#define IN_LL4(a,b,c,d)      ll a,b,c,d;  is >> a >> b >> c >> d;
#define IN_STR(s)            string s;    is >> s;

//////////////////////////////////////////////////////////////////////////
bool io_interactive = true;

istream& input()
{
  ios_base::sync_with_stdio(false);
  if (io_interactive)
    return cin;
#ifdef INPUT_FROM_FILE
  static ifstream is("AtCoder/input.txt");
  return is;
#endif
  if (!io_interactive)
    cin.tie(NULL);
  return cin;
}

ostream& output()
{
  cout << setprecision(15);
  if (!io_interactive)
    cout.tie(NULL);
  return cout;
}

template <typename T>
void init_v2(vector<vector<T>>& v, int lx, int ly, const T& val = T())
{
  v.resize(lx);
  FOR (i,0,lx)
    v[i].resize(ly, val);
};

//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//
////a
//int main()
//{
//  io_interactive = false;
//  istream& is = input();
//  ostream& os = output();
//
//  IN_INT2(a,b);
//  cout<<a*b-a-b+1;
//  return 0;
//}

//////////////////////////////////////////////////////////////////////////
//int main()
//{
//  io_interactive = false;
//  istream& is = input();
//  ostream& os = output();
//
//  IN_INT3(n,m,q);
//  vector<vector<int>> t,s;
//  init_v2(t,n,n,0);
//  init_v2(s,n,n,0);
//  FOR (i,0,m)
//  {
//    IN_INT2(l,r);    
//    ++t[l-1][r-1];
//  }
//
//  FOR (i,0,q)
//  {
//    IN_INT2(l,r); 
//    --r;
//    --l;
//    os<<s[r][r]-s[r][l]-s[l][r]-s[l][l];
//  }
//
//  //os << res;
//  return 0;
//}

//////////////////////////////////////////////////////////////////////////
////abc125_a
//int main()
//{
//  io_interactive = false;
//  istream& is = input();
//  ostream& os = output();
//  IN_INT3(a,b,t);
//  os<<b*(t/a);
//  return 0;
//}

//////////////////////////////////////////////////////////////////////////
////abc125_b
//int main()
//{
//  io_interactive = false;
//  istream& is = input();
//  ostream& os = output();
//
//  IN_INT(n);
//  vector<int> a(n);
//  FOR (i,0,n)
//    is >> a[i];
//  int res = 0;
//  FOR (i,0,n)
//  {
//    IN_INT(c);
//    res+=max(a[i]-c,0);
//  }
//  os << res;
//  return 0;
//}

//////////////////////////////////////////////////////////////////////////
////abc125_c
//int main()
//{
//  io_interactive = false;
//  istream& is = input();
//  ostream& os = output();
//
//  IN_INT(n);
//  unordered_set<int> s0,s1;
//  vector<int> a(n);
//  FOR (i,0,n)
//    is >> a[i];
//  s0.insert(0);
//  int g = a[0];
//  FOR (i,1,n)
//  {
//    s1.clear();
//    s1.insert(g);
//    FOR_EACH (it,s0)
//      s1.insert(gcd(*it,a[i]));
//    g = gcd(g,a[i]);
//    swap(s0,s1);
//  }
//  os << max(*max_element(ALL(s0)),g);
//  return 0;
//}

//////////////////////////////////////////////////////////////////////////
////abc125_d
//int main()
//{
//  io_interactive = false;
//  istream& is = input();
//  ostream& os = output();
//  //IN_INT(n);
//  //vector<int> a(n);
//  //int neg = 0;
//  //FOR (i,0,n)
//  //{
//  //  is >> a[i];
//  //  if (a[i]<0)
//  //    ++neg;
//  //  a[i]=abs(a[i]);
//  //}
//  //ll s = accumulate(ALL(a),0ll);
//  //if (neg&1)
//  //  s-=*min_element(ALL(a))<<1;
//  //os<<s;
//  IN_INT(n);
//  vector<int> a(n);
//  FOR (i,0,n)
//    is >> a[i];
//  pair<ll,ll> s0(a[0],-a[0]);
//  FOR (i,2,n)
//  {
//    pair<ll,ll> s1;
//    s1.first  = max(s0.first+a[i-1], s0.second-a[i-1]);
//    s1.second = max(s0.first-a[i-1], s0.second+a[i-1]);
//    s0 = s1;
//  }
//  os << max(s0.first+a[n-1], s0.second-a[n-1]);
//  return 0;
//}

//////////////////////////////////////////////////////////////////////////
////abc133_a
//int main()
//{
//  io_interactive = false;
//  istream& is = input();
//  ostream& os = output();
//
//  IN_INT3(n,a,b);
//  os << min(n*a,b);
//  return 0;
//}

//////////////////////////////////////////////////////////////////////////
//abc133_b
template<class T>
T is_square(T x)
{
  if (x < 0) return 0;
  T y = (T)sqrt((double)x);
  for (; y * y < x; ++y);
  return y * y == x ? y:0;
}

int main()
{
  io_interactive = false;
  istream& is = input();
  ostream& os = output();

  IN_INT2(n,d);
  vector<vector<int>> ps;
  init_v2(ps,n,d);

  FOR (i,0,n)
    FOR (j,0,d)
      is >> ps[i][j];

  int res = 0;
  FOR (i,0,n)
    FOR (j,0,i)
  {
    int s = 0;
    FOR (l,0,d)
      s += sqr(ps[i][l]-ps[j][l]);
    if (is_square(s))
      ++res;
  }


  os << res;
  return 0;
}


//////////////////////////////////////////////////////////////////////////

//int main()
//{
//  io_interactive = false;
//  istream& is = input();
//  ostream& os = output();
//
//  IN_INT(n);
//
//  //vector<int> a(n);
//  //FOR (i,0,n)
//  //  is >> a[i];
//
//  //int res = 0;
//  //os << res;
//  return 0;
//}



Measured memory_bytes: 256