#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;
class Buffer{
public:
int maxBuf,pos;
vector <char> Buff;
Buffer(char fileName[],int buffSize){
freopen(fileName,"r",stdin);
maxBuf = buffSize; Buff.resize(maxBuf);
reFill();
}
Buffer& operator>>(int &dest){
while(!isDigit(Buff[pos])){
pos++;
if(pos == maxBuf) reFill();
}
dest = 0;
while(isDigit(Buff[pos])){
dest = dest*10 + Buff[pos++] - '0';
if(pos == maxBuf) reFill();
}
return *this;
}
private:
bool isDigit(char c){
return c >= '0' & c <= '9';
}
void reFill(){
fread(&Buff[0],1,maxBuf,stdin); pos = 0;
}
};
const int prime[32] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 128};
int a[100001], b[100001], c[100001], n, d[128][128][128], nr, s = 1;
long long v[128], sol;
FILE *fout;
void bkt(int k) {
if(k == 31) {
int i, j, l, v[65];
long long temp;
temp = 0;
if(nr == 0)
return;
for(i = 0; i <= 64; ++i) {
v[i] = i % s;
}
for(i = 1; i <= n; ++i) {
++d[v[a[i]]][v[b[i]]][v[c[i]]];
}
for(i = 0; i < s; ++i) {
for(j = 0; j < s; ++j) {
for(l = 0; l <= s / 2; ++l) {
int newi = (s - i), newj = s - j, newl = s - l;
if(newi == s)newi = 0;
if(newj == s)newj = 0;
if(newl == s) newl = 0;
if(i == newi && j == newj && l == newl) {
temp += (long long) d[i][j][l] * (d[i][j][l] - 1) / 2;
d[i][j][l] = 0;
} else {
temp += (long long) d[i][j][l] * d[newi][newj][newl];
d[i][j][l] = d[newi][newj][newl] = 0;
}
}
}
}
//printf("%d\n", temp);
if(nr % 2 == 0) {
sol -= temp;
} else {
sol += temp;
}
} else {
bkt(k + 1);
++nr;
s *= prime[k];
if(s < 128)
bkt(k + 1);
--nr;
s /= prime[k];
}
}
int main() {
Buffer cin("puteri.in",1024*1024);
fout = fopen( "puteri.out", "w" );
int i;
cin >> n;
for(i = 1; i <= n; ++i)
cin >> a[i] >> b[i] >> c[i];
bkt(0);
fprintf(fout, "%lld\n", sol);
fclose( fout );
return 0;
}