#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
constexpr ll N=180,X=INT_MAX-18,Y=INT_MAX;
struct xhash
{
static const time_t T=time(0);
size_t operator()(const vector<int>&a)const
{
size_t h=0;
ll i,n=a.size();
for(i=0;i<n;i++)
{
h=(h*X+a[i])%Y;
}
return h*T%Y;
}
};
vector<int>a[N],sk;
unordered_set<vector<int>,xhash>ans;
vector<int>c;
ll n,m;
bool f;
inline vector<int>solveans()
{
ll k=c.size(),i,j;
vector<int> ans=a[c[k-1]];
for(i=k-2;i>=0;i--)
{
for(j=0;j<n;j++)ans[j]=a[c[i]][ans[j]-1];
}
return ans;
}
inline void dfs(ll x,ll cnt)
{
if(cnt)ans.insert(solveans());
if(cnt>=m)return;
ll i;
for(i=x;i<m;i++)
{
c.push_back(i);
dfs(i+1,cnt+1);
c.pop_back();
}
}
inline vector<int> operator^(const vector<int> &a,const vector<int> &b)
{
ll n=a.size(),i;
vector<int> c;
c.resize(n);
for(i=0;i<n;i++)c[i]=a[b[i]-1];
return c;
}
inline unordered_set<vector<int>,xhash>solve(ll l,ll r)
{
if(r-l<=1)
{
if(a[l]!=sk)return {a[l]};
else
{
f=1;
return {};
}
}
ll mid=(l+r)>>1;
unordered_set<vector<int>,xhash>res,al,ar;
vector<int>s;
al=solve(l,mid),ar=solve(mid,r);
for(auto&&i:al)res.insert(i);
for(auto&&i:ar)res.insert(i);
for(auto&&i:al)
{
for(auto&&j:ar)
{
s=i^j;
if(s!=sk)res.insert(s);
else f=1;
s=j^i;
if(s!=sk)res.insert(s);
else f=1;
}
}
return res;
}
int main()
{
ll i,j;
ios::sync_with_stdio(0),cin.tie(0);
cin>>n>>m;
for(i=0;i<m;i++)
{
a[i].resize(n);
for(j=0;j<n;j++)cin>>a[i][j];
}
if(m<=20)
{
dfs(0,0);
cout<<ans.size()<<'\n';
}
else
{
sk.resize(n);
iota(sk.begin(),sk.end(),1);
ll sum=solve(0,m).size();
cout<<sum+f<<'\n';
}
return 0;
}