#include <bits/stdc++.h>
using namespace std;
template <typename T1, typename T2>
istream& operator>>(istream& in, pair<T1, T2>& p) {
  in >> p.first >> p.second;
  return in;
}
template <typename T1, typename T2>
ostream& operator<<(ostream& out, pair<T1, T2>& p) {
  out << p.first << " " << p.second;
  return out;
}
template <typename T>
ostream& operator<<(ostream& out, vector<T>& v) {
  for (auto& i : v) {
    out << i << "\n";
  }
  return out;
}
const int MAX = 100007;
int union_find[MAX];
long long ranks[MAX];
bool vis[MAX];
int Find(int a) {
  if (union_find[a] != a) {
    union_find[a] = Find(union_find[a]);
  }
  return union_find[a];
}
void Union(int a, int b) {
  a = Find(a);
  b = Find(b);
  if (a != b) {
    union_find[b] = a;
    ranks[a] += ranks[b];
  }
}
vector<vector<int> > permutations;
int main() {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  ;
  int n, m;
  cin >> n >> m;
  for (int i = (0); i < (n); ++i) {
    union_find[i] = i;
    ranks[i] = 1;
  }
  permutations.resize(m);
  for (int i = (0); i < (m); ++i) {
    permutations[i].resize(n);
    int prev = -1;
    for (int j = (0); j < (n); ++j) {
      int a;
      cin >> a;
      --a;
      permutations[i][a] = prev;
      prev = a;
    }
  }
  for (int i = (0); i < (n); ++i) {
    int prev = permutations[0][i];
    bool works = true;
    if (prev != -1) {
      for (int j = (0); j < (m); ++j) {
        if (prev != permutations[j][i]) {
          works = false;
        }
      }
    } else {
      works = false;
    }
    if (works) {
      Union(i, prev);
    }
  }
  long long result = 0;
  for (int i = (0); i < (n); ++i) {
    int temp = Find(i);
    if (!vis[temp]) {
      vis[temp] = true;
      result += ((ranks[temp] + 1ll) * ranks[temp]) / 2ll;
    }
  }
  cout << result;
  return 0;
}
