//
// Created by zhujunchao on 2021/4/29.
//

#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
#include <cassert>
#include <map>
using namespace std;
const int N = 2e5 + 7;
long long gcd(long long a, long long b){
    return b == 0 ? a : gcd(b, a % b);
}
struct FS{
    long long a = 0, b = 0;
    FS(){};
    FS(long long _a, long long _b){
        a = _a; b = _b;
    }
    bool operator < (const FS &r)const{
        __int128 u = a, v = b;
        u *= r.b;
        v *= r.a;
        return u < v;
    }
    bool operator != (const FS &r)const{
        return a != r.a || b != r.b;
    }
    bool operator == (const FS &r)const{
        return a == r.a && b == r.b;
    }
};
map<FS, int> ma;
vector<vector<pair<int, int> > > t;
struct POINT{
    FS x, y, k;
    POINT(){};
    POINT(FS _x, FS _y){
        x = _x;
        y = _y;
    }
}p[N];
struct POO{
    FS k, ok; int idx;
    bool operator < (const POO &r)const{
        if(k != r.k) return k < r.k;
        return ok < r.ok;
    }
}p2[N * 2];
void yf(FS &w){
    long long g = gcd(w.a, w.b);
    w.a /= g; w.b /= g;
}
bool vis[N * 2];
vector<pair<int, int> > ans;
int dfs(int x, int fa,int o){
//    cout << x << " " << o << endl;
    int nw = -1;
    vis[o] = 1;
    for(auto v: t[x]){
        if(vis[v.second]) continue;
        int tmp = dfs(v.first, x, v.second);
//        cout << x << " " << v.first << " " << tmp << endl;
        if(tmp != -1){
            ans.push_back(make_pair(v.second, tmp));
        }
        else if(nw != -1){
            ans.push_back(make_pair(v.second, nw));
            nw = -1;
        }
        else nw = v.second;
    }
    return nw;
}
int main(){
    int n;
    int cnt = 0;
    scanf("%d", &n);
    t.resize(n * 2 + 1);
    for(int i = 1; i <= n; i++){
        scanf("%lld%lld%lld%lld", &p[i].x.a, &p[i].x.b, &p[i].y.a, &p[i].y.b);
        p[i].k = FS(p[i].y.a * p[i].x.b, p[i].x.a * p[i].y.b);
        POINT tmp = p[i];
        tmp.x.a += tmp.x.b;
        FS r;
        r.a = tmp.y.a * tmp.x.b;
        r.b = tmp.x.a * tmp.y.b;
        yf(r);
        p2[i * 2 - 1].idx = i;
        p2[i * 2 - 1].k = r;
        if(!ma.count(r)) ma[r] = ++cnt;
        p2[i * 2 - 1].ok = p[i].k;
        FS r2;
        tmp = p[i];
        tmp.y.a += tmp.y.b;
        r2.a = tmp.y.a * tmp.x.b;
        r2.b = tmp.x.a * tmp.y.b;
        yf(r2);
        p2[i * 2].idx = i;
        p2[i * 2].k = r2;
        if(!ma.count(r2)) ma[r2] = ++cnt;
        p2[i * 2].ok = p[i].k;
        t[ma[r2]].push_back(make_pair(ma[r], i));
        t[ma[r]].push_back(make_pair(ma[r2], i));
//        cout << ma[r] << " " << ma[r2] << " " << i << endl;
    }
    for(int i = 1; i <= cnt; i++){
        dfs(i, 0, 0);
    }
    printf("%d\n", ans.size());
    for(auto sg: ans){
        assert(sg.first != sg.second);
        printf("%d %d\n", sg.first, sg.second);
    }
    return 0;
}