Problem:
問題 C : Apples
問題文
あるところに銃の腕に自信をもつ猟師がいました．
猟師はある日，「ウィリアムテルというスイス人が，息子の頭にりんごを乗せて遠くから矢で撃ち落とすパフォーマンスで有名になった」というお話を聞きました．
それを聞いて"自分のほうがもっと凄い!!"と思った猟師は動いている人の上にりんごを乗せて撃ちぬくパフォーマンスを考えつきました．
猟師は広場に
N
人の人を集め，それぞれの人の上にりんごを乗せました．
i
番目の人は時刻
t=0
のとき，座標
(x_i,  y_i)
にいます．
そこから単位時間あたり速度ベクトル
(u_i,  v_i)
にしたがって歩きます．
すなわち，時刻
t  ≥  0
のとき，
i
番目の人は座標
(x_i + t \times u_i  ,   y_i + t \times v_i)
にいます．
ここで，人々は十分小さいので，同じ座標に複数の人がいたり，同じ座標ですれ違ったりできると仮定します．
猟師は人々を驚嘆させるために，一発の弾丸でできるだけ多くのりんごを撃ち落とすことにしました．
猟師は
t ≥ 0
であるような任意の時刻に，任意の座標から任意の方向に向けて弾丸を放つことができます．
放たれた弾丸は無限の速さで直線軌道で移動し，りんごに当たった場合貫通して移動します．
弾丸を一発だけ打つとき，最大で何個のりんごを撃ち落とせるか計算してください．
入力形式
入力は以下の形式で与えられる
N
x_0
y_0
u_0
v_0
...
x_{N-1}
y_{N-1}
u_{N-1}
v_{N-1}
出力形式
撃ち落とせるりんごの最大個数を1行に出力せよ．
制約
1 ≤ N ≤ 200
0 ≤   |x_i|,   |y_i|    ≤ 10
0 ≤   |u_i|,   |v_i|   ≤ 3
入力値はすべて整数である。
入出力例
入力例 1
5
0 0 0 0
1 0 -1 1
-1 0 1 -1
1 1 -1 1
-1 -1 1 -1
出力例 1
5
時刻１に５人がｙ軸上に並ぶので最大５つのりんごを撃ち落とせる．
入力例 2
5
0 0 0 0
1 0 1 0
-1 0 -1 0
1 1 1 1
-1 -1 -1 -1
出力例 2
3
入力例 3
15
-10 9 2 1
2 10 0 -1
-10 -4 0 -3
-2 8 0 -1
0 -10 -1 -2
-8 5 0 -1
-7 -8 -3 1
10 -6 -2 -3
9 -6 1 0
10 -5 3 1
10 1 0 -3
-4 7 0 -1
10 -9 2 2
2 -5 -1 1
9 -10 3 1
出力例 3
5

Submitted solutions:

code_snippet: #include <bits/stdc++.h>
using namespace std;
typedef long long ll;
template<class T>bool chmax(T &a, const T &b) { if (a<b) { a=b; return true; } return false; }
template<class T>bool chmin(T &a, const T &b) { if (b<a) { a=b; return true; } return false; }
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define mp make_pair
#define si(x) int(x.size())
const int mod=998244353,MAX=300005;
const ll INF=15LL<<58;

//幾何ライブラリ
// define double ll をするときは Point の < と == も書き換えよう！

const double eps=1e-8;
const double pi=acos((double)-1.0L);
#define equals(a,b) (fabs((a)-(b))<eps)

double torad(double deg) {return (double)(deg)*pi/180.0;}
double todeg(double ang) {return ang*180.0/pi;}

class Point{
public:
    double x,y;
    
    Point(double x=0,double y=0):x(x),y(y){}
    
    Point operator + (Point p){return Point(x+p.x,y+p.y);}
    Point operator - (Point p){return Point(x-p.x,y-p.y);}
    Point operator * (double a){return Point(a*x,a*y);}
    Point operator / (double a){return Point(x/a,y/a);}
    
    double abs(){return sqrt(norm());}
    double norm(){return x*x+y*y;}
    
    bool operator < (const Point &p)const{
        return x+eps<p.x||(equals(x,p.x)&&y+eps<p.y);
//return x<p.x||(x==p.x&&y<p.y);
    }
    
    bool operator == (const Point &p)const{
        return fabs(x-p.x)<eps/100000&&fabs(y-p.y)<eps/100000;
//return x==p.x&&y==p.y;
    }
};

typedef Point Vector;

double norm(Vector a){
    return a.x*a.x+a.y*a.y;
}

double abs(Vector a){
    return sqrt(norm(a));
}

double dot(Vector a,Vector b){
    return a.x*b.x+a.y*b.y;
}

double cross(Vector a,Vector b){
    return a.x*b.y-a.y*b.x;
}

struct Segment{
    Point p1,p2;
};

bool isOrthogonal(Vector a,Vector b){
    return equals(dot(a,b),0.0);
}

bool isOrthogonal(Point a1,Point a2,Point b1,Point b2){
    return isOrthogonal(a1-a2,b1-b2);
}

bool isOrthogonal(Segment s1,Segment s2){
    return equals(dot(s1.p2-s1.p1,s2.p2-s2.p1),0.0);
}

bool isParallel(Vector a,Vector b){
    return equals(cross(a,b),0.0);
}

bool isParallel(Point a1,Point a2,Point b1,Point b2){
    return isParallel(a1-a2,b1-b2);
}

bool isParallel(Segment s1,Segment s2){
    return equals(cross(s1.p2-s1.p1,s2.p2-s2.p1),0.0);
}

Point project(Segment s,Point p){
    Vector base=s.p2-s.p1;
    double r=dot(p-s.p1,base)/norm(base);
    return s.p1+base*r;
}

Point reflect(Segment s,Point p){
    return p+(project(s,p)-p)*2.0;
}

Point turn(Point p,Point c,double pi){
    double q=atan2(p.y-c.y,p.x-c.x);
    q+=pi;
    p=c+Point{cos(q)*abs(p-c),sin(q)*abs(p-c)};
    
    return p;
}
//pをcを中心としてpi回転させる(1周で2π)
//p=cのときnan

//p0,p1,p2の順に見たときどうなるか？

static const int counter_clockwise=1;
static const int clockwise=-1;
static const int online_back=2;
static const int online_front=-2;
static const int on_segment=0;

int ccw(Point p0,Point p1,Point p2){
    Vector a=p1-p0;
    Vector b=p2-p0;
    
    if(cross(a,b)>eps) return counter_clockwise;
    if(cross(a,b)<-eps) return clockwise;
    if(dot(a,b)<-eps) return online_back;
    if(a.norm()<b.norm()) return online_front;
    
    return on_segment;
}

bool intersect(Point p1,Point p2,Point p3,Point p4){
    return(ccw(p1,p2,p3)*ccw(p1,p2,p4)<=0&&ccw(p3,p4,p1)*ccw(p3,p4,p2)<=0);
}

bool intersect(Segment s1,Segment s2){
    return intersect(s1.p1,s1.p2,s2.p1,s2.p2);
}

bool overlap(Segment s1,Segment s2){
    int a=ccw(s1.p1,s1.p2,s2.p1),b=ccw(s1.p1,s1.p2,s2.p2);
    if(a&1||b&1) return 0;
    if(a==2){
        if(b==-2||(b==0&&!(s2.p2==s1.p1))) return 1;
        else return 0;
    }
    if(a==-2){
        if(b==2||(b==0&&!(s2.p2==s1.p2))) return 1;
        else return 0;
    }
    if(a==0){
        if(s1.p1==s2.p1){
            if(b!=2) return 1;
            else return 0;
        }
        else if(s1.p2==s2.p1){
            if(b!=-2) return 1;
            else return 0;
        }
        else return 1;
    }
    return 0;
}
//s1とs2の共通の線分(長さ0より大きい)があるかどうか

typedef Segment Line;

double getDistance(Point a,Point b){
    return abs(a-b);
}

double getDistanceLP(Line l,Point p){
    return abs(cross(l.p2-l.p1,p-l.p1)/abs(l.p2-l.p1));
}

double getDistanceSP(Segment s,Point p){
    if(dot(s.p2-s.p1,p-s.p1)<0.0) return abs(p-s.p1);
    if(dot(s.p1-s.p2,p-s.p2)<0.0) return abs(p-s.p2);
    return getDistanceLP(s,p);
}

double getDistance(Segment s1,Segment s2){
    if(intersect(s1,s2)) return 0.0;
    return min({getDistanceSP(s1,s2.p1),getDistanceSP(s1,s2.p2),getDistanceSP(s2,s1.p1),getDistanceSP(s2,s1.p2)});
}

Point getCrossPointS(Segment s1,Segment s2){
    //if(ccw(s1.p1,s1.p2,s2.p1)==0&&ccw(s1.p1,s1.p2,s2.p2)==0) return s1.p1;
    Vector base=s2.p2-s2.p1;
    double d1=abs(cross(base,s1.p1-s2.p1));
    double d2=abs(cross(base,s1.p2-s2.p1));
    double t=d1/(d1+d2);
    return s1.p1+(s1.p2-s1.p1)*t;
}//同じ時壊れます

Point getCrossPointL(Line l1,Line l2){
    //if(ccw(s1.p1,s1.p2,s2.p1)==0&&ccw(s1.p1,s1.p2,s2.p2)==0) return s1.p1;
    
    Vector v1=l1.p2-l1.p1,v2=l2.p2-l2.p1;
    
    return l1.p1+v1*cross(v2,l2.p1-l1.p1)/cross(v2,v1);
}

Segment ParallelSegment(Segment s,double d){
    Vector v={-(s.p2-s.p1).y,(s.p2-s.p1).x};
    v=v/abs(v);
    
    s.p1=s.p1+v*d;
    s.p2=s.p2+v*d;
    
    return s;
}

Point naisin(Point p1,Point p2,Point p3){
    if(p1==p2&&p2==p3&&p3==p1) return p1;
    
    return (p1*abs(p2-p3)+p2*abs(p1-p3)+p3*abs(p1-p2))/(abs(p2-p3)+abs(p1-p3)+abs(p1-p2));
}

Point naisin(Line l1,Line l2,Line l3){
    //平行でない前提
    
    Point p1=getCrossPointL(l1,l2),p2=getCrossPointL(l1,l3),p3=getCrossPointL(l2,l3);
    return naisin(p1,p2,p3);
}

//ネットの適当を書いたのであってるか全く知りません→あってそう

class Circle{
public:
    Point c;
    double r;
    Circle(Point c=Point(),double r=0.0):c(c),r(r){}
};

Point CircleCenter(Point a,Point b,Point c){
    Point u=a-b,v=a-c;
    double m1=(norm(a)-norm(b))/2.0,m2=(norm(a)-norm(c))/2.0;
    
    Point res;
    if(cross(u,v)==0.0){
        res.x=1e9;
        res.y=1e9;
        
        return res;
    }
    res.x=(m1*v.y-m2*u.y)/cross(u,v);
    res.y=(m1*v.x-m2*u.x)/cross(v,u);
    
    return res;
}
//3点を通る円の中心を返す

//交わる 0
// c1がc2のinside 1
// c1がc2のoutside 2
// 交わらない 3

int not_intersect(Circle c1,Circle c2){
    double d=getDistance(c1.c,c2.c);
    double r1=c1.r,r2=c2.r;
    if(r1<r2){
        if(d<(r2-r1)) return 1;
    }
    if(r1>r2){
        if(d<(r1-r2)) return 2;
    }
    if(d<=r1+r2) return 0;
    else return 3;
}

pair<Point,Point> segCrossPpoints(Circle c,Line l){
    //assert(intersect(c,l));
    Vector pr=project(l,c.c);
    Vector e=(l.p2-l.p1)/abs(l.p2-l.p1);
    double base=sqrt(c.r*c.r-norm(pr-c.c));
    return make_pair(pr+e*base,pr-e*base);
}

double arg(Vector p){return atan2(p.y,p.x);}
Vector polar(double a,double r){return Point(cos(r)*a,sin(r)*a);}

//inside(outside)

pair<Point,Point> getCrossPoints(Circle c1,Circle c2){
    //assert(intersect(c1,c2));
    double d=abs(c1.c-c2.c);
    double a=acos((c1.r*c1.r+d*d-c2.r*c2.r)/(2*c1.r*d));
    double t=arg(c2.c-c1.c);
    return make_pair(c1.c+polar(c1.r,t+a),c1.c+polar(c1.r,t-a));
}

vector<Line> Commontangent(Circle c1,Circle c2){
    vector<Line> res;
    Point p=c2.c-c1.c;
    
    if(abs(p)>=(c1.r+c2.r)){
        Point a,b;
        a.x=c1.r*(p.x*(c1.r+c2.r)+p.y*sqrt(norm(p)-(c1.r+c2.r)*(c1.r+c2.r)))/norm(p);
        a.y=c1.r*(p.y*(c1.r+c2.r)-p.x*sqrt(norm(p)-(c1.r+c2.r)*(c1.r+c2.r)))/norm(p);
        
        b.x=c1.r*(p.x*(c1.r+c2.r)-p.y*sqrt(norm(p)-(c1.r+c2.r)*(c1.r+c2.r)))/norm(p);
        b.y=c1.r*(p.y*(c1.r+c2.r)+p.x*sqrt(norm(p)-(c1.r+c2.r)*(c1.r+c2.r)))/norm(p);
        
        res.push_back(Line{a+c1.c,a+c1.c+Point{-a.y,a.x}});
        if(!(a==b)){
            res.push_back(Line{b+c1.c,b+c1.c+Point{-b.y,b.x}});
        }
    }
    
    if(abs(p)>=abs(c1.r-c2.r)){
        Point a,b;
        a.x=c1.r*(p.x*(c1.r-c2.r)+p.y*sqrt(norm(p)-(c1.r-c2.r)*(c1.r-c2.r)))/norm(p);
        a.y=c1.r*(p.y*(c1.r-c2.r)-p.x*sqrt(norm(p)-(c1.r-c2.r)*(c1.r-c2.r)))/norm(p);
        
        b.x=c1.r*(p.x*(c1.r-c2.r)-p.y*sqrt(norm(p)-(c1.r-c2.r)*(c1.r-c2.r)))/norm(p);
        b.y=c1.r*(p.y*(c1.r-c2.r)+p.x*sqrt(norm(p)-(c1.r-c2.r)*(c1.r-c2.r)))/norm(p);
        
        res.push_back(Line{a+c1.c,a+c1.c+Point{-a.y,a.x}});
        if(!(a==b)){
            res.push_back(Line{b+c1.c,b+c1.c+Point{-b.y,b.x}});
        }
    }
    
    return res;
}

typedef vector<Point> Polygon;

/*
 IN 2
 ON 1
 OUT 0
 */

int contains(Polygon g,Point p){
    int n=int(g.size());
    bool x=false;
    for(int i=0;i<n;i++){
        Point a=g[i]-p,b=g[(i+1)%n]-p;
        if(a.y>b.y) swap(a,b);
        if(a.y<eps&&0<b.y&&cross(a,b)<0) x=!x;
        if(abs(cross(a,b))<eps&&dot(a,b)<eps) return 1;
    }
    return (x?2:0);
}

Polygon andrewScan(Polygon s,bool ok){
    Polygon u,l;
    sort(all(s));
    
    if(int(s.size())<3) return s;
    int n=int(s.size());
    
    u.push_back(s[0]);
    u.push_back(s[1]);
    
    l.push_back(s[n-1]);
    l.push_back(s[n-2]);
    
    if(ok){
        for(int i=2;i<n;i++){
            for(int j=int(u.size());j>=2&&ccw(u[j-2],u[j-1],s[i])==counter_clockwise;j--){
                u.pop_back();
            }
            u.push_back(s[i]);
        }
        
        for(int i=int(s.size())-3;i>=0;i--){
            for(int j=int(l.size());j>=2&&ccw(l[j-2],l[j-1],s[i])==counter_clockwise;j--){
                l.pop_back();
            }
            l.push_back(s[i]);
        }
    }
    
    if(!ok){
        for(int i=2;i<n;i++){
            for(int j=int(u.size());j>=2&&ccw(u[j-2],u[j-1],s[i])!=clockwise;j--){
                u.pop_back();
            }
            u.push_back(s[i]);
        }
        
        for(int i=int(s.size())-3;i>=0;i--){
            for(int j=int(l.size());j>=2&&ccw(l[j-2],l[j-1],s[i])!=clockwise;j--){
                l.pop_back();
            }
            l.push_back(s[i]);
        }
    }
    
    reverse(all(l));
    
    for(int i=int(u.size())-2;i>=1;i--) l.push_back(u[i]);
    
    return l;
}//ok==1なら辺の上も含める

Polygon convex_cut(const Polygon& P, const Line& l) {
    Polygon Q;
    for(int i=0;i<si(P);i++){
        Point A=P[i],B=P[(i+1)%si(P)];
        if(ccw(l.p1,l.p2,A)!=-1)Q.push_back(A);
        if(ccw(l.p1,l.p2,A)*ccw(l.p1,l.p2,B)<0) Q.push_back(getCrossPointL(Line{A,B},l));
    }
    return Q;
}

double area(Point a,Point b,Point c){
    b=b-a;
    c=c-a;
    return abs(b.x*c.y-b.y*c.x)/2.0;
}

/*

ll area(Polygon P){
    ll sum=0;
    for(int i=0;i<si(P);i++){
        sum+=cross(P[i],P[(i+1)%si(P)]);
    }
    return abs(sum);
}

*/

// 倍

double area(Polygon &P){
    if(si(P)==0) return 0.0;
    double res=0;
    Point c={0.0,0.0};
    for(int i=0;i<si(P);i++){
        c=c+P[i];
    }
    c=c/si(P);
    
    for(int i=0;i<si(P);i++){
        res+=area(c,P[i],P[(i+1)%si(P)]);
    }
    
    return res;
}

ll gcd(ll a,ll b){
    if(b==0) return a;
    return gcd(b,a%b);
}

pair<Point,Vector> perpendicular_bisector(Point a,Point b){
    Point c=(a+b)/2;
    Vector v=b-c;
    swap(v.x,v.y);
    v.x*=-1;
    
    Point p=c;
    if(v.x==0){
        v.y=1;
        p.y=0;
    }
    else if(v.y==0){
        v.x=1;
        p.x=0;
    }
    else{
        if(v.x<0){
            v.x*=-1;
            v.y*=-1;
        }
        ll g=gcd(abs(ll(v.x)),abs(ll(v.y)));
        v.x/=g;
        v.y/=g;
        if(p.x>=0){
            ll d=p.x/v.x;
            p=p-v*d;
        }else{
            ll d=abs(p.x)/v.x;
            p=p+v*d;
            
            if(p.x<0){
                p=p+v;
            }
        }
    }
    
    return mp(p,v);
}
//2倍するなりして整数にしておくこと

/*
Line perpendicular_bisector(Point a,Point b){
    Point c=(a+b)/2;
    Point d=turn(a,c,M_PI/2.0);
    
    return {c,d};
}
//2倍するなりして整数にしておくこと
*/
pair<Line,Line> angle_bisector(Line a,Line b){
    // assert(!isParallel(a,b));
    
    Point p=getCrossPointL(a,b);
    
    if(a.p1==p) swap(a.p1,a.p2);
    if(b.p1==p) swap(b.p1,b.p2);
    
    double kaku1=arg(a.p1-p);
    double kaku2=arg(b.p1-p);
    
    return mp(Line{p,p+polar(1.0,(kaku1+kaku2)/2.0)},Line{p,p+polar(1.0,(kaku1+kaku2+M_PI)/2.0)});
    
}

Line abc_to_line(double a,double b,double c){
    if(a==0){
        return {{0,-c/b},{1,-c/b}};
    }else{
        if(b==0){
            return {{-c/a,0},{-c/a,1}};
        }else{
            return {{0,-c/b},{1,-(a+c)/b}};
        }
    }
}

int main(){
    
    std::ifstream in("text.txt");
    std::cin.rdbuf(in.rdbuf());
    cin.tie(0);
    ios::sync_with_stdio(false);
    
    int N;cin>>N;
    vector<double> x(N),y(N),vx(N),vy(N);
    vector<Point> P(N),V(N);
    set<pair<double,double>> SE;
    for(int i=0;i<N;i++){
        double a,b,c,d;cin>>a>>b>>c>>d;
        x[i]=a;
        y[i]=b;
        vx[i]=c;
        vy[i]=d;
        P[i]={a,b};
        V[i]={c,d};
        SE.insert(mp(x[i],y[i]));
    }
    
    if(si(SE)<=2){
        cout<<N<<endl;
        return 0;
    }
    
    int ans=min(2,N);
    
    auto solve=[&](double t,int a,int b){
        if(t<0) return;
        //cout<<t<<" "<<id<<endl;
        vector<Point> A(N);
        for(int i=0;i<N;i++){
            A[i]={x[i]+t*vx[i],y[i]+t*vy[i]};
        }
        if(A[a]==A[b]){
            int cn=0;
            for(int i=0;i<N;i++){
                if(A[i]==A[a]) cn++;
            }
            chmax(ans,cn);
            return;
        }
        
        int cn=0;
        for(int i=0;i<N;i++){
            if(ccw(A[a],A[b],A[i])%2==0) cn++;
        }
        chmax(ans,cn);
    };
    
    for(int d=0;d<N;d++){
        for(int a=d+1;a<N;a++){
            for(int b=a+1;b<N;b++){
                double p=((vx[a]-vx[d])*(vy[b]-vy[d])-(vy[a]-vy[d])*(vx[b]-vx[d]));
                double q=((vx[a]-vx[d])*(y[b]-y[d])+(x[a]-x[d])*(vy[b]-vy[d])-(vy[a]-vy[d])*(x[b]-x[d])-(y[a]-y[d])*(vx[b]-vx[d]));
                double r=((x[a]-x[d])*(y[b]-y[d])-(y[a]-y[d])*(x[b]-x[d]));
                
                if(p==0){
                    if(q==0){
                        solve(1,d,a);
                        solve(1,a,b);
                        solve(1,b,d);
                    }else{
                        double t=(-r)/q;
                        solve(t,d,a);
                        solve(t,a,b);
                        solve(t,b,d);
                    }
                }else{
                    if(q*q-4*p*r>=0){
                        double t1=(-q-sqrt(q*q-4*p*r))/(2*p);
                        double t2=(-q+sqrt(q*q-4*p*r))/(2*p);
                        solve(t1,d,a);
                        solve(t1,a,b);
                        solve(t1,b,d);
                        solve(t2,d,a);
                        solve(t2,a,b);
                        solve(t2,b,d);
                    }
                }
            }
        }
    }
    
    for(int a=0;a<N;a++){
        for(int b=a+1;b<N;b++){
            solve(0,a,b);
        }
    }
    
    cout<<ans<<endl;
}
accuracy: 1
time_ms: 3870
memory_kb: 3608
final_rank: 9

code_snippet: #include <iostream>
#include <vector>
#include <cmath>
#include <tuple>
#include <algorithm>
using namespace std;

struct Point {
	double px, py;
};

Point operator+(const Point &a1, const Point &a2) {
	return Point{ a1.px + a2.px, a1.py + a2.py };
}

Point operator-(const Point &a1, const Point &a2) {
	return Point{ a1.px - a2.px, a1.py - a2.py };
}

Point operator*(const Point &a1, const double &a2) {
	return Point{ a1.px * a2, a1.py * a2 };
}

bool operator==(const Point &a1, const Point &a2) {
	if (abs(a1.px - a2.px) < 1e-7 && abs(a1.py - a2.py) < 1e-7) return true;
	return false;
}

// Solve ax^2 + bx + c = 0
vector<double> Equation(int a, int b, int c) {
	if (a == 0 && b == 0) {
		if (c == 0) return vector<double>{ 10000.0 };
		return vector<double>{};
	}
	if (a == 0) return vector<double>{ -1.0 * c / b };
	int val = b * b - 4 * a * c;
	if (val < 0) return vector<double>{};
	double ans1 = (-1.0 * b + sqrt(1.0 * val)) / (2.0 * a);
	double ans2 = (-1.0 * b - sqrt(1.0 * val)) / (2.0 * a);
	return vector<double>{ ans1, ans2 };
}

int N;
Point G[209], V[209];

int solve(double Time, int idx1, int idx2) {
	Point P1 = G[idx1] + (V[idx1] * Time);
	Point P2 = G[idx2] + (V[idx2] * Time);
	int cnt1 = 0;
	int cnt2 = 0;
	for (int j = 1; j <= N; j++) {
		Point P3 = (G[j] + V[j] * Time);
		Point Diff1 = P2 - P1;
		Point Diff2 = P3 - P1;
		double crs = Diff1.px * Diff2.py - Diff1.py * Diff2.px;
		if (abs(crs) < 1e-7 && !(P1 == P2)) cnt1 += 1;
		if (P1 == P3) cnt2 += 1;
	}
	return max({3, cnt1, cnt2});
}

int main() {
	// Input
	cin >> N;
	for (int i = 1; i <= N; i++) cin >> G[i].px >> G[i].py >> V[i].px >> V[i].py;
	if (N <= 2) {
		cout << N << endl;
		return 0;
	}
	
	// Brute Force
	int Answer = 2;
	for (int i = 1; i <= N; i++) {
		for (int j = 1; j <= N; j++) {
			for (int k = 1; k <= N; k++) {
				if (i == j || j == k || k == i || i > j) continue;
				Point Diff1 = G[j] - G[i];
				Point Velo1 = V[j] - V[i];
				Point Diff2 = G[k] - G[i];
				Point Velo2 = V[k] - V[i];
				int pa = Velo1.px * Velo2.py - Velo1.py * Velo2.px;
				int pb = Diff1.px * Velo2.py + Velo1.px * Diff2.py - Diff1.py * Velo2.px - Velo1.py * Diff2.px;
				int pc = Diff1.px * Diff2.py - Diff1.py * Diff2.px;
				vector<double> tup = Equation(pa, pb, pc);
				for (int l = 0; l < (int)tup.size(); l++) {
					if (tup[l] < -1.0e-7) continue;
					int ret = solve(tup[l], i, j);
					Answer = max(Answer, ret);
				}
			}
		}
	}
	
	// Output
	cout << Answer << endl;
	return 0;
}
accuracy: 1
time_ms: 3580
memory_kb: 3508
final_rank: 8

code_snippet: #include <iostream>
#include <vector>
#include <cmath>
#include <tuple>
#include <algorithm>
using namespace std;

struct Point {
	double px, py;
};

Point operator+(const Point &a1, const Point &a2) {
	return Point{ a1.px + a2.px, a1.py + a2.py };
}

Point operator-(const Point &a1, const Point &a2) {
	return Point{ a1.px - a2.px, a1.py - a2.py };
}

Point operator*(const Point &a1, const double &a2) {
	return Point{ a1.px * a2, a1.py * a2 };
}

bool operator==(const Point &a1, const Point &a2) {
	if (abs(a1.px - a2.px) < 1e-7 && abs(a1.py - a2.py) < 1e-7) return true;
	return false;
}

// Solve ax^2 + bx + c = 0
vector<double> Equation(int a, int b, int c) {
	if (a == 0 && b == 0) {
		if (c == 0) return vector<double>{ 10000.0 };
		return vector<double>{};
	}
	if (a == 0) return vector<double>{ -1.0 * c / b };
	int val = b * b - 4 * a * c;
	if (val < 0) return vector<double>{};
	double ans1 = (-1.0 * b + sqrt(1.0 * val)) / (2.0 * a);
	double ans2 = (-1.0 * b - sqrt(1.0 * val)) / (2.0 * a);
	return vector<double>{ ans1, ans2 };
}

int N;
Point G[209], V[209];

int main() {
	// Input
	cin >> N;
	for (int i = 1; i <= N; i++) cin >> G[i].px >> G[i].py >> V[i].px >> V[i].py;
	if (N <= 2) {
		cout << N << endl;
		return 0;
	}
	
	// Brute Force
	vector<tuple<double, int, int, int>> Cand;
	for (int i = 1; i <= N; i++) {
		for (int j = i + 1; j <= N; j++) {
			for (int k = j + 1; k <= N; k++) {
				Point Diff1 = G[j] - G[i];
				Point Velo1 = V[j] - V[i];
				Point Diff2 = G[k] - G[i];
				Point Velo2 = V[k] - V[i];
				int pa = Velo1.px * Velo2.py - Velo1.py * Velo2.px;
				int pb = Diff1.px * Velo2.py + Velo1.px * Diff2.py - Diff1.py * Velo2.px - Velo1.py * Diff2.px;
				int pc = Diff1.px * Diff2.py - Diff1.py * Diff2.px;
				vector<double> tup = Equation(pa, pb, pc);
				for (int l = 0; l < (int)tup.size(); l++) {
					if (tup[l] < -1.0e-7) continue;
					Cand.push_back(make_tuple(tup[l], i, j, k));
				}
			}
		}
	}
	int Answer = 2;
	if ((int)Cand.size() >= 1) Answer = 3;
	sort(Cand.begin(), Cand.end());
	
	// Get Answer: Part 1
	for (int i = 0; i < (int)Cand.size(); i++) {
		// if (i < (int)Cand.size() - 3 && abs(get<0>(Cand[i]) - get<0>(Cand[i+3])) < 1e-7) continue;
		int idx1 = get<1>(Cand[i]);
		int idx2 = get<2>(Cand[i]);
		Point P1 = G[idx1] + (V[idx1] * get<0>(Cand[i]));
		Point P2 = G[idx2] + (V[idx2] * get<0>(Cand[i]));
		
		// Count Points on Line & Same as P1
		int cnt1 = 0;
		int cnt2 = 0;
		for (int j = 1; j <= N; j++) {
			Point P3 = (G[j] + V[j] * get<0>(Cand[i]));
			Point Diff1 = P2 - P1;
			Point Diff2 = P3 - P1;
			double crs = Diff1.px * Diff2.py - Diff1.py * Diff2.px;
			if (abs(crs) < 1e-7 && !(P1 == P2)) cnt1 += 1;
			if (P1 == P3) cnt2 += 1;
		}
		Answer = max(Answer, cnt1);
		Answer = max(Answer, cnt2);
	}
	
	// Output
	cout << Answer << endl;
	return 0;
}
accuracy: 0.48717948717948717
time_ms: 690
memory_kb: 54136
final_rank: 12

code_snippet: #include <iostream>
#include <vector>
#include <cmath>
#include <tuple>
#include <algorithm>
using namespace std;

struct Point {
	double px, py;
};

Point operator+(const Point &a1, const Point &a2) {
	return Point{ a1.px + a2.px, a1.py + a2.py };
}

Point operator-(const Point &a1, const Point &a2) {
	return Point{ a1.px - a2.px, a1.py - a2.py };
}

Point operator*(const Point &a1, const double &a2) {
	return Point{ a1.px * a2, a1.py * a2 };
}

bool operator==(const Point &a1, const Point &a2) {
	if (abs(a1.px - a2.px) < 1e-7 && abs(a1.py - a2.py) < 1e-7) return true;
	return false;
}

// Solve ax^2 + bx + c = 0
vector<double> Equation(int a, int b, int c) {
	if (a == 0 && b == 0) {
		if (c == 0) return vector<double>{ 10000.0 };
		return vector<double>{};
	}
	if (a == 0) return vector<double>{ -1.0 * c / b };
	int val = b * b - 4 * a * c;
	if (val < 0) return vector<double>{};
	double ans1 = (-1.0 * b + sqrt(1.0 * val)) / (2.0 * a);
	double ans2 = (-1.0 * b - sqrt(1.0 * val)) / (2.0 * a);
	return vector<double>{ ans1, ans2 };
}

int N;
Point G[209], V[209];

int main() {
	// Input
	cin >> N;
	for (int i = 1; i <= N; i++) cin >> G[i].px >> G[i].py >> V[i].px >> V[i].py;
	if (N <= 2) {
		cout << N << endl;
		return 0;
	}
	
	// Brute Force
	vector<tuple<double, int, int, int>> Cand;
	for (int i = 1; i <= N; i++) {
		for (int j = i + 1; j <= N; j++) {
			for (int k = j + 1; k <= N; k++) {
				Point Diff1 = G[j] - G[i];
				Point Velo1 = V[j] - V[i];
				Point Diff2 = G[k] - G[i];
				Point Velo2 = V[k] - V[i];
				int pa = Velo1.px * Velo2.py - Velo1.py * Velo2.px;
				int pb = Diff1.px * Velo2.py + Velo1.px * Diff2.py - Diff1.py * Velo2.px - Velo1.py * Diff2.px;
				int pc = Diff1.px * Diff2.py - Diff1.py * Diff2.px;
				vector<double> tup = Equation(pa, pb, pc);
				for (int l = 0; l < (int)tup.size(); l++) {
					if (tup[l] < -1.0e-7) continue;
					Cand.push_back(make_tuple(tup[l], i, j, k));
				}
			}
		}
	}
	int Answer = 2;
	if ((int)Cand.size() >= 1) Answer = 3;
	sort(Cand.begin(), Cand.end());
	
	// Get Answer: Part 1
	for (int i = 0; i < (int)Cand.size(); i++) {
		if (i < (int)Cand.size() - 3 && abs(get<0>(Cand[i]) - get<0>(Cand[i+3])) < 1e-7) continue;
		int idx1 = get<1>(Cand[i]);
		int idx2 = get<2>(Cand[i]);
		Point P1 = G[idx1] + (V[idx1] * get<0>(Cand[i]));
		Point P2 = G[idx2] + (V[idx2] * get<0>(Cand[i]));
		
		// Count Points on Line & Same as P1
		int cnt1 = 0;
		int cnt2 = 0;
		for (int j = 1; j <= N; j++) {
			Point P3 = (G[j] + V[j] * get<0>(Cand[i]));
			Point Diff1 = P2 - P1;
			Point Diff2 = P3 - P1;
			double crs = Diff1.px * Diff2.py - Diff1.py * Diff2.px;
			if (abs(crs) < 1e-7 && !(P1 == P2)) cnt1 += 1;
			if (P1 == P3) cnt2 += 1;
		}
		Answer = max(Answer, cnt1);
		Answer = max(Answer, cnt2);
	}
	
	// Output
	cout << Answer << endl;
	return 0;
}
accuracy: 0.41025641025641024
time_ms: 100
memory_kb: 54052
final_rank: 13

code_snippet: #pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")
#include<iostream>
#include<string>
#include<cstdio>
#include<vector>
#include<cmath>
#include<algorithm>
#include<functional>
#include<iomanip>
#include<queue>
#include<ciso646>
#include<random>
#include<map>
#include<set>
#include<bitset>
#include<stack>
#include<unordered_map>
#include<unordered_set>
#include<utility>
#include<cassert>
#include<complex>
#include<numeric>
#include<array>
#include<chrono>
using namespace std;

//#define int long long
typedef long long ll;

typedef unsigned long long ul;
typedef unsigned int ui;
constexpr ll mod = 998244353;
const ll INF = mod * mod;
typedef pair<int, int>P;

#define rep(i,n) for(int i=0;i<n;i++)
#define per(i,n) for(int i=n-1;i>=0;i--)
#define Rep(i,sta,n) for(int i=sta;i<n;i++)
#define rep1(i,n) for(int i=1;i<=n;i++)
#define per1(i,n) for(int i=n;i>=1;i--)
#define Rep1(i,sta,n) for(int i=sta;i<=n;i++)
#define all(v) (v).begin(),(v).end()
typedef pair<ll, ll> LP;

template<typename T>
void chmin(T& a, T b) {
	a = min(a, b);
}
template<typename T>
void chmax(T& a, T b) {
	a = max(a, b);
}
template<typename T>
void cinarray(vector<T>& v) {
	rep(i, v.size())cin >> v[i];
}
template<typename T>
void coutarray(vector<T>& v) {
	rep(i, v.size()) {
		if (i > 0)cout << " "; cout << v[i];
	}
	cout << "\n";
}
ll mod_pow(ll x, ll n, ll m = mod) {
	if (n < 0) {
		ll res = mod_pow(x, -n, m);
		return mod_pow(res, m - 2, m);
	}
	if (abs(x) >= m)x %= m;
	if (x < 0)x += m;
	if (x == 0)return 0;
	ll res = 1;
	while (n) {
		if (n & 1)res = res * x % m;
		x = x * x % m; n >>= 1;
	}
	return res;
}
struct modint {
	int n;
	modint() :n(0) { ; }
	modint(ll m) {
		if (m < 0 || mod <= m) {
			m %= mod; if (m < 0)m += mod;
		}
		n = m;
	}
	operator int() { return n; }
};
bool operator==(modint a, modint b) { return a.n == b.n; }
modint operator+=(modint& a, modint b) { a.n += b.n; if (a.n >= mod)a.n -= mod; return a; }
modint operator-=(modint& a, modint b) { a.n -= b.n; if (a.n < 0)a.n += mod; return a; }
modint operator*=(modint& a, modint b) { a.n = ((ll)a.n * b.n) % mod; return a; }
modint operator+(modint a, modint b) { return a += b; }
modint operator-(modint a, modint b) { return a -= b; }
modint operator*(modint a, modint b) { return a *= b; }
modint operator^(modint a, ll n) {
	if (n == 0)return modint(1);
	modint res = (a * a) ^ (n / 2);
	if (n % 2)res = res * a;
	return res;
}

ll inv(ll a, ll p) {
	return (a == 1 ? 1 : (1 - p * inv(p % a, a)) / a + p);
}
modint operator/(modint a, modint b) { return a * modint(inv(b, mod)); }
modint operator/=(modint& a, modint b) { a = a / b; return a; }
const int max_n = 1 << 20;
modint fact[max_n], factinv[max_n];
void init_f() {
	fact[0] = modint(1);
	for (int i = 0; i < max_n - 1; i++) {
		fact[i + 1] = fact[i] * modint(i + 1);
	}
	factinv[max_n - 1] = modint(1) / fact[max_n - 1];
	for (int i = max_n - 2; i >= 0; i--) {
		factinv[i] = factinv[i + 1] * modint(i + 1);
	}
}
modint comb(int a, int b) {
	if (a < 0 || b < 0 || a < b)return 0;
	return fact[a] * factinv[b] * factinv[a - b];
}
modint combP(int a, int b) {
	if (a < 0 || b < 0 || a < b)return 0;
	return fact[a] * factinv[a - b];
}

ll gcd(ll a, ll b) {
	a = abs(a); b = abs(b);
	if (a < b)swap(a, b);
	while (b) {
		ll r = a % b; a = b; b = r;
	}
	return a;
}
typedef long double ld;
typedef pair<ld, ld> LDP;
const ld eps = 1e-8;
const ld pi = acosl(-1.0);
int dx[4] = { 1,0,-1,0 };
int dy[4] = { 0,1,0,-1 };

using mP = pair<modint, modint>;
//-----------------------------------

bool ison(ld cx1, ld cy1, ld cx2, ld cy2, ld cx3, ld cy3) {
	ld val = abs((cx2 - cx1) * (cy3 - cy1) - (cx3 - cx1) * (cy2 - cy1));
	return val < eps;
}
vector<ld> calc(int a, int b, int c) {
	if (a == 0) {
		if (b == 0)return {};
		if (-c > 0) {
			return { -c / (ld)b };
		}
		return {};
	}
	if (b * b - 4 * a * c < 0)return {};
	vector<ld> res;
	ld t1= (-b + sqrt(b * b - 4 * a * c)) / (ld)(2 * a);
	if (t1 > 0) {
		res.push_back(t1);
	}
	ld t2= (-b - sqrt(b * b - 4 * a * c)) / (ld)(2 * a);
	if (t2 > 0) {
		res.push_back(t2);
	}
	return res;
}
void solve() {
	int n; cin >> n;
	vector<int> x(n), y(n), vx(n), vy(n);
	rep(i, n) {
		cin >> x[i] >> y[i] >> vx[i] >> vy[i];
	}
	int ans = 2;
	auto calccnt = [&](ld t, int i, int j) {
		ld cx1 = x[i] + t * vx[i];
		ld cy1 = y[i] + t * vy[i];
		ld cx2 = x[j] + t * vx[j];
		ld cy2 = y[j] + t * vy[j];
		int cnt = 2;
		if (abs(cx1 - cx2) < eps && abs(cy1 - cy2) < eps) {
			rep(k, n) {
				if (k != i && k != j) {
					ld cx3 = x[k] + t * vx[k];
					ld cy3 = y[k] + t * vy[k];
					if (abs(cx1 - cx3) < eps && abs(cy1 - cy3) < eps)cnt++;
				}
			}
		}
		else {
			rep(k, n)if (k != i && k != j) {
				ld cx3 = x[k] + t * vx[k];
				ld cy3 = y[k] + t * vy[k];
				if (ison(cx1, cy1, cx2, cy2, cx3, cy3))cnt++;
			}
		}
		return cnt;
	};
	rep(i, n)Rep(j, i + 1, n)Rep(k, j + 1, n) {
		int ax = x[j] - x[i];
		int ay = y[j] - y[i];
		int bx = x[k] - x[i];
		int by = y[k] - y[i];
		int dx = vx[j] - vx[i];
		int dy = vy[j] - vy[i];
		int ux = vx[k] - vx[i];
		int uy = vy[k] - vy[i];

		int a = dx * uy - dy * ux;
		int b = dx * by + ax * uy - ay * ux - dy * bx;
		int c = ax * by - ay * bx;
		auto vt = calc(a, b, c);
		for (auto t : vt) {
			if (t < 0)continue;
			//assert(t >= 0);
			chmax(ans, calccnt(t, i, j));
			chmax(ans, calccnt(t, i, k));
			chmax(ans, calccnt(t, j, k));
		}
	}
	rep(i, n)Rep(j, i + 1, n) {
		chmax(ans, calccnt(0, i, j));
	}
	cout << ans << "\n";
}


signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	//cout << fixed << setprecision(10);
	//init_f();
	//init();
	//while(true)
	//expr();
	//int t; cin >> t; rep(i, t)
	solve();
	return 0;
}
accuracy: 1
time_ms: 1470
memory_kb: 11656
final_rank: 7

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 1000000000000000000
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;



#define SIZE 205

struct Point{
	Point(double arg_x,double arg_y){
		x = arg_x;
		y = arg_y;
	}

	Point(){
		x = y = 0.0;
	}

	Point operator + (Point p){ return Point(x+p.x,y+p.y); }
	Point operator - (Point p){ return Point(x-p.x,y-p.y);}
	Point operator * (double a){ return Point(a*x,a*y); }
	Point operator / (double a){ return Point(x/a,y/a); }

	double abs(){ return sqrt(norm()); }
	double norm(){ return x*x + y*y; }

	bool operator<(const Point &p) const{
		return x != p.x? x < p.x: y < p.y;
	}

	bool operator == (const Point &p) const{
		return fabs(x-p.x) < EPS && fabs(y-p.y) < EPS;
	}


	/*void debug(){

		printf("(%.3lf,%.3lf)\n",x,y);
	}*/

	double x,y;
};

struct Data{

	int int_x,int_y;
};

struct Info{
	Info(int arg_index,int arg_num){
		index = arg_index;
		num = arg_num;
	}
	int index,num;
};

struct Pos{

	double slope,add;
};

typedef Point Vector;

struct Line{
	Line(){

	}
	Line(Point a,Point b){
		p[0] = a;
		p[1] = b;
	}
	/*void outPut(){

		printf("(%.3lf,%.3lf)-(%.3lf,%.3lf)\n",p[0].x,p[0].y,p[1].x,p[1].y);
	}*/
	Point p[2];
};

int N;
double vec_slope[SIZE],work_vec_slope[SIZE];
bool check[SIZE],work[SIZE];
Data int_point[SIZE],int_vec[SIZE],work_int_point[SIZE],work_int_vec[SIZE];
Point point[SIZE],vec[SIZE],work_point[SIZE],work_vec[SIZE];
vector<Info> info;
map<double,int> MAP;


double calc_slope(Line A){

	if(fabs(A.p[0].x-A.p[1].x) < EPS){

		return DBL_MAX;

	}else if(fabs(A.p[0].y-A.p[1].y) < EPS){

		return 0;

	}else{

		return (A.p[1].y-A.p[0].y)/(A.p[1].x-A.p[0].x);
	}
}

//傾きと切片を計算する関数
Pos calc_pos(Line A){

	double slope = calc_slope(A);
	double add;

	if(fabs(slope-DBL_MAX) < EPS){

		add = 0;

	}else if(fabs(slope) < EPS){

		add = A.p[0].y;

	}else{

		add = A.p[0].y-slope*A.p[0].x;
	}

	Pos ret;
	ret.slope = slope;
	ret.add = add;

	return ret;
}

//点iと点kが原点線上に並ぶ時刻を求める
vector<double> calc_equation(int i,int k){

	vector<double> ret;

	ll int_a = work_int_point[i].int_x,int_b = work_int_point[i].int_y,int_p = work_int_vec[i].int_x,int_q = work_int_vec[i].int_y;
	ll int_c = work_int_point[k].int_x,int_d = work_int_point[k].int_y,int_r = work_int_vec[k].int_x,int_s = work_int_vec[k].int_y;
	double a = work_point[i].x,b=work_point[i].y,p = work_vec[i].x,q = work_vec[i].y;
	double c = work_point[k].x,d=work_point[k].y,r = work_vec[k].x,s = work_vec[k].y;

	ll int_A = int_p*int_s-int_q*int_r;
	ll int_B = int_a*int_s+int_d*int_p-(int_b*int_r+int_c*int_q);
	ll int_C = int_a*int_d-int_b*int_c;
	ll int_D = int_B*int_B-4*int_A*int_C;

	double A = p*s-q*r;
	double B = a*s+d*p-(b*r+c*q);
	double C = a*d-b*c;
	double D = B*B-4*A*C;

	if(int_A == 0){
		if(int_B == 0){
			if(int_C == 0){
				ret.push_back(-HUGE_NUM);
			}
			return ret;
		}
		double tmp_t = (-C/B);
		if(tmp_t > 0){

			ret.push_back(tmp_t);
		}
		return ret;
	}
	if(int_D < 0){

		return ret;

	}else{

		double t1 = (-B+sqrt(D))/(2*A),t2 = (-B-sqrt(D))/(2*A);

		if(int_D == 0){

			if(t1 >= 0){

				ret.push_back(t1);
			}
			return ret;
		}else{

			if(t1 >= 0){

						ret.push_back(t1);
					}
					return ret;


			if(t2 >= 0){

				ret.push_back(t2);
			}
			return ret;
		}
	}
}

bool is_same_vec(int i,int k){

	if(int_vec[i].int_x==int_vec[k].int_x && int_vec[i].int_y == int_vec[k].int_y){

		return true;
	}else{

		return false;
	}
}

bool is_rev_vec(int i,int k){

	if(int_vec[i].int_x==-int_vec[k].int_x && int_vec[i].int_y == -int_vec[k].int_y){

		return true;

	}else{

		return false;
	}
}

double norm(Vector a){
	return a.x*a.x+a.y*a.y;
}

double abs(Vector a){
	return sqrt(norm(a));
}

Point calc_T_point(int index,double T){

	Point ret = Point(work_point[index].x+work_vec[index].x*T,work_point[index].y+work_vec[index].y*T);
	return ret;
}

bool isSame(Point a,Point b){

	if(abs(a-b) < EPS){

		return true;
	}else{

		return false;
	}
}


int main(){

	scanf("%d",&N);

	for(int i = 0; i < N; i++){

		scanf("%d %d %d %d",&int_point[i].int_x,&int_point[i].int_y,&int_vec[i].int_x,&int_vec[i].int_y);
		point[i].x = int_point[i].int_x;
		point[i].y = int_point[i].int_y;
		vec[i].x = int_vec[i].int_x;
		vec[i].y = int_vec[i].int_y;

		if(int_vec[i].int_x == 0){

			vec_slope[i] = DBL_MAX;

		}else{

			vec_slope[i] = vec[i].y/vec[i].x;
		}
	}

	if(N <= 2){

		printf("%d\n",N);
		return 0;
	}

	//点の重複を除く
	for(int i = 0; i < N; i++){

		check[i] = false;
	}

	for(int i = 0; i < N; i++){
		if(check[i])continue;

		int num = 1;

		for(int k = i+1; k < N; k++){
			if(int_point[i].int_x == int_point[k].int_x && int_point[i].int_y == int_point[k].int_y
					&& int_vec[i].int_x == int_vec[k].int_x && int_vec[i].int_y == int_vec[k].int_y){
				num++;
				check[k] = true;
			}
		}
		info.push_back(Info(i,num));
	}

	if(info.size() <= 2){

		printf("%d\n",N);
		return 0;
	}

	int a,b;
	Line tmp_line;
	Pos pos;

	int ans = 0,count;

	for(int i = 0; i < info.size()-1; i++){
		a = info[i].index;
		for(int k = i+1; k < info.size(); k++){
			b = info[k].index;

			tmp_line.p[0] = point[a],tmp_line.p[1] = point[b];
			//時刻0の直線の傾きと切片を求める
			pos = calc_pos(tmp_line);

			//時刻0の,a-b直線上の個数を数える
			count = info[i].num+info[k].num;
			for(int p = 0; p < info.size(); p++){
				if(p == i || p == k)continue;

				if(fabs(pos.slope-DBL_MAX) < EPS){ //垂直

					if(int_point[info[p].index].int_x == int_point[a].int_x){
						count += info[p].num;
					}

				}else{

					if(fabs(point[info[p].index].y-(pos.slope*point[info[p].index].x+pos.add)) < EPS){
						count += info[p].num;
					}
				}
			}

			ans = max(ans,count);

			//2点を通る直線の傾きと切片が永遠に同じ場合
			if((is_same_vec(a,b)||is_rev_vec(a,b))&&fabs(pos.slope-fabs(vec_slope[a])) < EPS){

				for(int p = 0; p < N; p++)work[p] = false;

				count = info[i].num+info[k].num;

				//同一直線上にある、他の同一直線上を動く点を探す(これらも永遠に当該直線状に存在する)
				for(int p = 0; p < info.size(); p++){
					if(p == i || p == k)continue;

					if(fabs(pos.slope-DBL_MAX) < EPS){ //垂直

						if(int_point[info[p].index].int_x == int_point[a].int_x && int_vec[info[p].index].int_x == 0){

							count += info[p].num;
							work[p] = true;
						}

					}else{

						if(fabs(point[info[p].index].y-(pos.slope*point[info[p].index].x+pos.add)) < EPS &&
								(is_same_vec(a,info[p].index)||is_rev_vec(a,info[p].index))){

							count += info[p].num;
							work[p] = true;
						}
					}
				}

				MAP.clear();
				ans = max(ans,count);

				//点aを原点に固定する
				for(int p = 0; p < N; p++){
					if(p == a)continue;

					work_int_point[p].int_x = int_point[p].int_x-int_point[a].int_x;
					work_int_point[p].int_y = int_point[p].int_y-int_point[a].int_y;
					work_int_vec[p].int_x = int_vec[p].int_x-int_vec[a].int_x;
					work_int_vec[p].int_y = int_vec[p].int_y-int_vec[a].int_y;

					work_point[p] = point[p]-point[a];
					work_vec[p] = vec[p]-vec[a];
				}

				for(int p = 0; p < info.size(); p++){
					if(p == i || p == k || work[p])continue;

					vector<double> v_a;

					v_a =  calc_equation(info[p].index,a);
					if(v_a.size() == 0)continue;

					if(v_a.size() == 1 && fabs(v_a[0]+HUGE_NUM) < EPS){

						count++;
						continue;
					}

					for(int r = 0; r < v_a.size(); r++){

						auto at = MAP.lower_bound(v_a[r]-EPS);
						if(at == MAP.end()){

							ans = max(ans,count+info[p].num);
							MAP[v_a[r]] = info[p].num;
						}else{

							if(fabs(v_a[r]-at->first) < EPS){

								ans = max(ans,count+at->second+info[p].num);
								at->second += info[p].num;
							}else{
								ans = max(ans,count+info[p].num);
								MAP[v_a[r]] = info[p].num;
							}
						}
					}
				}

			}else if(is_same_vec(a,b)){ //2点の方向ベクトルが同じ場合

				//点aを原点に固定する:点aと点bを通る直線は永遠に変わらない
				for(int p = 0; p < N; p++){

					work_int_point[p].int_x = int_point[p].int_x-int_point[a].int_x;
					work_int_point[p].int_y = int_point[p].int_y-int_point[a].int_y;
					work_int_vec[p].int_x = int_vec[p].int_x-int_vec[a].int_x;
					work_int_vec[p].int_y = int_vec[p].int_y-int_vec[a].int_y;

					work_point[p] = point[p]-point[a];
					work_vec[p] = vec[p]-vec[a];

					if(fabs(work_vec[p].x) < EPS){

						work_vec_slope[p] = DBL_MAX;
					}else{

						work_vec_slope[p] = work_vec[p].y/work_vec[p].x;
					}
				}

				//傾きを再度計算
				tmp_line.p[0] = work_point[a],tmp_line.p[1] = work_point[b];
				pos = calc_pos(tmp_line);

				for(int p = 0; p < info.size(); p++)work[p] = false;

				count = info[i].num+info[k].num;

				//同一直線上にある、他の同一直線上を動く点を探す
				for(int p = 0; p < info.size(); p++){
					if(p == i || p == k)continue;

					if(fabs(pos.slope-DBL_MAX) < EPS){ //垂直
						//x座標がaと同じで左右方向に動かない
						if(work_int_point[info[p].index].int_x == work_int_point[a].int_x && work_int_vec[info[p].index].int_x == 0){

							count += info[p].num;
							work[p] = true;
						}

					}else{

						if(fabs(work_point[info[p].index].y-(pos.slope*work_point[info[p].index].x+pos.add)) < EPS && //原点線上に存在
								(fabs(pos.slope-fabs(work_vec_slope[info[p].index])) < EPS)){ //かつ、傾きの絶対値が原点線と同じ

							count += info[p].num;
							work[p] = true;
						}
					}
				}

				MAP.clear();
				ans = max(ans,count);

				for(int p = 0; p < info.size(); p++){
					if(p == i || p == k || work[p])continue;

					vector<double> v_a;

					v_a =  calc_equation(b,info[p].index);
					if(v_a.size() == 0)continue;
					if(v_a.size() == 1 && fabs(v_a[0]+HUGE_NUM) < EPS){

						count++;
						continue;
					}

					for(int r = 0; r < v_a.size(); r++){

						auto at = MAP.lower_bound(v_a[r]-EPS);
						if(at == MAP.end()){

							ans = max(ans,count+info[p].num);
							MAP[v_a[r]] = info[p].num;
						}else{

							if(fabs(v_a[r]-at->first) < EPS){

								ans = max(ans,count+at->second+info[p].num);
								at->second += info[p].num;
							}else{
								ans = max(ans,count+info[p].num);
								MAP[v_a[r]] = info[p].num;
							}
						}
					}
				}

			}else{

				//連立方程式を解く
				count = info[i].num+info[k].num;
				MAP.clear();

				//点aを原点に固定する
				for(int p = 0; p < N; p++){

					work_int_point[p].int_x = int_point[p].int_x-int_point[a].int_x;
					work_int_point[p].int_y = int_point[p].int_y-int_point[a].int_y;
					work_int_vec[p].int_x = int_vec[p].int_x-int_vec[a].int_x;
					work_int_vec[p].int_y = int_vec[p].int_y-int_vec[a].int_y;

					work_point[p] = point[p]-point[a];
					work_vec[p] = vec[p]-vec[a];
				}

				count = 2;

				Line line1,line2,line3;
				Point p1,p2,p3;

				for(int p = 0; p < info.size(); p++){
					if(p == i || p == k)continue;

					vector<double> tmp_vec;

					//aとpを結ぶ線は常に原点線なので、bとpについてのみ見れば良い
					tmp_vec = calc_equation(b,info[p].index);
					if(tmp_vec.size() == 1 && fabs(tmp_vec[0]+HUGE_NUM) < EPS){
						//判別式の係数が全て0は重なる
						count += info[p].num;
						continue;
					}

					if(tmp_vec.size() == 0)continue;

					for(int q = 0; q < tmp_vec.size(); q++){

						double T = tmp_vec[q];

						//aとbが重なる時刻はSKIP(異なる[原点を通る直線]を同一と見なしてしまうため)
						Point tmp_p = calc_T_point(b,T);
						if(isSame(tmp_p,work_point[a])){
							ans = max(ans,count+info[p].num);
							continue;
						}

						auto at = MAP.lower_bound(T-EPS);

						if(at == MAP.end()){

							ans = max(ans,count+info[p].num);
							MAP[T] = info[p].num;
						}else{

							if(fabs(T-at->first) < EPS){

								ans = max(ans,count+at->second+info[p].num);
								at->second += info[p].num;
							}else{
								ans = max(ans,count+info[p].num);
								MAP[T] = info[p].num;
							}
						}
					}
				}
			}
		}
	}

	printf("%d\n",ans);

	return 0;
}
accuracy: 1
time_ms: 250
memory_kb: 3272
final_rank: 2

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 1000000000000000000
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;



#define SIZE 205

struct Point{
	Point(double arg_x,double arg_y){
		x = arg_x;
		y = arg_y;
	}

	Point(){
		x = y = 0.0;
	}

	Point operator + (Point p){ return Point(x+p.x,y+p.y); }
	Point operator - (Point p){ return Point(x-p.x,y-p.y);}
	Point operator * (double a){ return Point(a*x,a*y); }
	Point operator / (double a){ return Point(x/a,y/a); }

	double abs(){ return sqrt(norm()); }
	double norm(){ return x*x + y*y; }

	bool operator<(const Point &p) const{
		return x != p.x? x < p.x: y < p.y;
	}

	bool operator == (const Point &p) const{
		return fabs(x-p.x) < EPS && fabs(y-p.y) < EPS;
	}


	/*void debug(){

		printf("(%.3lf,%.3lf)\n",x,y);
	}*/

	double x,y;
};

struct Data{

	int int_x,int_y;
};

struct Info{
	Info(int arg_index,int arg_num){
		index = arg_index;
		num = arg_num;
	}
	int index,num;
};

struct Pos{

	double slope,add;
};

typedef Point Vector;

struct Line{
	Line(){

	}
	Line(Point a,Point b){
		p[0] = a;
		p[1] = b;
	}
	/*void outPut(){

		printf("(%.3lf,%.3lf)-(%.3lf,%.3lf)\n",p[0].x,p[0].y,p[1].x,p[1].y);
	}*/
	Point p[2];
};

int N;
double vec_slope[SIZE],work_vec_slope[SIZE];
bool check[SIZE],work[SIZE];
Data int_point[SIZE],int_vec[SIZE],work_int_point[SIZE],work_int_vec[SIZE];
Point point[SIZE],vec[SIZE],work_point[SIZE],work_vec[SIZE];
vector<Info> info;
map<double,int> MAP;


double calc_slope(Line A){

	if(fabs(A.p[0].x-A.p[1].x) < EPS){

		return DBL_MAX;

	}else if(fabs(A.p[0].y-A.p[1].y) < EPS){

		return 0;

	}else{

		return (A.p[1].y-A.p[0].y)/(A.p[1].x-A.p[0].x);
	}
}

//傾きと切片を計算する関数
Pos calc_pos(Line A){

	double slope = calc_slope(A);
	double add;

	if(fabs(slope-DBL_MAX) < EPS){

		add = 0;

	}else if(fabs(slope) < EPS){

		add = A.p[0].y;

	}else{

		add = A.p[0].y-slope*A.p[0].x;
	}

	Pos ret;
	ret.slope = slope;
	ret.add = add;

	return ret;
}

//点iと点kが原点線上に並ぶ時刻を求める
vector<double> calc_equation(int i,int k){

	vector<double> ret;

	ll int_a = work_int_point[i].int_x,int_b = work_int_point[i].int_y,int_p = work_int_vec[i].int_x,int_q = work_int_vec[i].int_y;
	ll int_c = work_int_point[k].int_x,int_d = work_int_point[k].int_y,int_r = work_int_vec[k].int_x,int_s = work_int_vec[k].int_y;
	double a = work_point[i].x,b=work_point[i].y,p = work_vec[i].x,q = work_vec[i].y;
	double c = work_point[k].x,d=work_point[k].y,r = work_vec[k].x,s = work_vec[k].y;

	ll int_A = int_p*int_s-int_q*int_r;
	ll int_B = int_a*int_s+int_d*int_p-(int_b*int_r+int_c*int_q);
	ll int_C = int_a*int_d-int_b*int_c;
	ll int_D = int_B*int_B-4*int_A*int_C;

	double A = p*s-q*r;
	double B = a*s+d*p-(b*r+c*q);
	double C = a*d-b*c;
	double D = B*B-4*A*C;

	if(int_A == 0){
		if(int_B == 0){
			if(int_C == 0){
				ret.push_back(-HUGE_NUM);
			}
			return ret;
		}
		double tmp_t = (-C/B);
		if(tmp_t > 0){

			ret.push_back(tmp_t);
		}
		return ret;
	}
	if(int_D < 0){

		return ret;

	}else{

		double t1 = (-B+sqrt(D))/(2*A),t2 = (-B-sqrt(D))/(2*A);

		if(int_D == 0){

			if(t1 >= 0){

				ret.push_back(t1);
			}
			return ret;
		}else{

			if(t1 >= 0){

						ret.push_back(t1);
					}
					return ret;


			if(t2 >= 0){

				ret.push_back(t2);
			}
			return ret;
		}
	}
}

bool is_same_vec(int i,int k){

	if(int_vec[i].int_x==int_vec[k].int_x && int_vec[i].int_y == int_vec[k].int_y){

		return true;
	}else{

		return false;
	}
}

bool is_rev_vec(int i,int k){

	if(int_vec[i].int_x==-int_vec[k].int_x && int_vec[i].int_y == -int_vec[k].int_y){

		return true;

	}else{

		return false;
	}
}

double norm(Vector a){
	return a.x*a.x+a.y*a.y;
}

double abs(Vector a){
	return sqrt(norm(a));
}

Point calc_T_point(int index,double T){

	Point ret = Point(work_point[index].x+work_vec[index].x*T,work_point[index].y+work_vec[index].y*T);
	return ret;
}

bool isSame(Point a,Point b){

	if(abs(a-b) < EPS){

		return true;
	}else{

		return false;
	}
}


int main(){

	scanf("%d",&N);

	for(int i = 0; i < N; i++){

		scanf("%d %d %d %d",&int_point[i].int_x,&int_point[i].int_y,&int_vec[i].int_x,&int_vec[i].int_y);
		point[i].x = int_point[i].int_x;
		point[i].y = int_point[i].int_y;
		vec[i].x = int_vec[i].int_x;
		vec[i].y = int_vec[i].int_y;

		if(int_vec[i].int_x == 0){

			vec_slope[i] = DBL_MAX;

		}else{

			vec_slope[i] = vec[i].y/vec[i].x;
		}
	}

	if(N <= 2){

		printf("%d\n",N);
		return 0;
	}

	//点の重複を除く
	for(int i = 0; i < N; i++){

		check[i] = false;
	}

	for(int i = 0; i < N; i++){
		if(check[i])continue;

		int num = 1;

		for(int k = i+1; k < N; k++){
			if(int_point[i].int_x == int_point[k].int_x && int_point[i].int_y == int_point[k].int_y
					&& int_vec[i].int_x == int_vec[k].int_x && int_vec[i].int_y == int_vec[k].int_y){
				num++;
				check[k] = true;
			}
		}
		info.push_back(Info(i,num));
	}

	if(info.size() <= 2){

		printf("%d\n",N);
		return 0;
	}

	int a,b;
	Line tmp_line;
	Pos pos;

	int ans = 0,count;

	for(int i = 0; i < info.size()-1; i++){
		a = info[i].index;
		for(int k = i+1; k < info.size(); k++){
			b = info[k].index;

			tmp_line.p[0] = point[a],tmp_line.p[1] = point[b];
			//時刻0の直線の傾きと切片を求める
			pos = calc_pos(tmp_line);

			//時刻0の,a-b直線上の個数を数える
			count = info[i].num+info[k].num;
			for(int p = 0; p < info.size(); p++){
				if(p == i || p == k)continue;

				if(fabs(pos.slope-DBL_MAX) < EPS){ //垂直

					if(int_point[info[p].index].int_x == int_point[a].int_x){
						count += info[p].num;
					}

				}else{

					if(fabs(point[info[p].index].y-(pos.slope*point[info[p].index].x+pos.add)) < EPS){
						count += info[p].num;
					}
				}
			}

			ans = max(ans,count);

			//2点を通る直線の傾きと切片が永遠に同じ場合
			if((is_same_vec(a,b)||is_rev_vec(a,b))&&fabs(pos.slope-fabs(vec_slope[a])) < EPS){

				for(int p = 0; p < N; p++)work[p] = false;

				count = info[i].num+info[k].num;

				//同一直線上にある、他の同一直線上を動く点を探す(これらも永遠に当該直線状に存在する)
				for(int p = 0; p < info.size(); p++){
					if(p == i || p == k)continue;

					if(fabs(pos.slope-DBL_MAX) < EPS){ //垂直

						if(int_point[info[p].index].int_x == int_point[a].int_x && int_vec[info[p].index].int_x == 0){

							count += info[p].num;
							work[p] = true;
						}

					}else{

						if(fabs(point[info[p].index].y-(pos.slope*point[info[p].index].x+pos.add)) < EPS &&
								(is_same_vec(a,info[p].index)||is_rev_vec(a,info[p].index))){

							count += info[p].num;
							work[p] = true;
						}
					}
				}

				MAP.clear();
				ans = max(ans,count);

				//点aを原点に固定する
				for(int p = 0; p < N; p++){
					if(p == a)continue;

					work_int_point[p].int_x = int_point[p].int_x-int_point[a].int_x;
					work_int_point[p].int_y = int_point[p].int_y-int_point[a].int_y;
					work_int_vec[p].int_x = int_vec[p].int_x-int_vec[a].int_x;
					work_int_vec[p].int_y = int_vec[p].int_y-int_vec[a].int_y;

					work_point[p] = point[p]-point[a];
					work_vec[p] = vec[p]-vec[a];
				}

				for(int p = 0; p < info.size(); p++){
					if(p == i || p == k || work[p])continue;

					vector<double> v_a;

					v_a =  calc_equation(info[p].index,a);
					if(v_a.size() == 0)continue;

					if(v_a.size() == 1 && fabs(v_a[0]+HUGE_NUM) < EPS){

						count++;
						continue;
					}

					for(int r = 0; r < v_a.size(); r++){

						auto at = MAP.lower_bound(v_a[r]-EPS);
						if(at == MAP.end()){

							ans = max(ans,count+info[p].num);
							MAP[v_a[r]] = info[p].num;
						}else{

							if(fabs(v_a[r]-at->first) < EPS){

								ans = max(ans,count+at->second+info[p].num);
								at->second += info[p].num;
							}else{
								ans = max(ans,count+info[p].num);
								MAP[v_a[r]] = info[p].num;
							}
						}
					}
				}

			}else if(is_same_vec(a,b)){ //2点の方向ベクトルが同じ場合

				//点aを原点に固定する:点aと点bを通る直線は永遠に変わらない
				for(int p = 0; p < N; p++){

					work_int_point[p].int_x = int_point[p].int_x-int_point[a].int_x;
					work_int_point[p].int_y = int_point[p].int_y-int_point[a].int_y;
					work_int_vec[p].int_x = int_vec[p].int_x-int_vec[a].int_x;
					work_int_vec[p].int_y = int_vec[p].int_y-int_vec[a].int_y;

					work_point[p] = point[p]-point[a];
					work_vec[p] = vec[p]-vec[a];

					if(fabs(work_vec[p].x) < EPS){

						work_vec_slope[p] = DBL_MAX;
					}else{

						work_vec_slope[p] = work_vec[p].y/work_vec[p].x;
					}
				}

				//傾きを再度計算
				tmp_line.p[0] = work_point[a],tmp_line.p[1] = work_point[b];
				pos = calc_pos(tmp_line);

				for(int p = 0; p < info.size(); p++)work[p] = false;

				count = info[i].num+info[k].num;

				//同一直線上にある、他の同一直線上を動く点を探す
				for(int p = 0; p < info.size(); p++){
					if(p == i || p == k)continue;

					if(fabs(pos.slope-DBL_MAX) < EPS){ //垂直
						//x座標がaと同じで左右方向に動かない
						if(work_int_point[info[p].index].int_x == work_int_point[a].int_x && work_int_vec[info[p].index].int_x == 0){

							count += info[p].num;
							work[p] = true;
						}

					}else{

						if(fabs(work_point[info[p].index].y-(pos.slope*work_point[info[p].index].x+pos.add)) < EPS && //原点線上に存在
								(fabs(pos.slope-fabs(work_vec_slope[info[p].index])) < EPS)){ //かつ、傾きの絶対値が原点線と同じ

							count += info[p].num;
							work[p] = true;
						}
					}
				}

				MAP.clear();
				ans = max(ans,count);

				for(int p = 0; p < info.size(); p++){
					if(p == i || p == k || work[p])continue;

					vector<double> v_a;

					v_a =  calc_equation(b,info[p].index);
					if(v_a.size() == 0)continue;
					if(v_a.size() == 1 && fabs(v_a[0]+HUGE_NUM) < EPS){

						count++;
						continue;
					}

					for(int r = 0; r < v_a.size(); r++){

						auto at = MAP.lower_bound(v_a[r]-EPS);
						if(at == MAP.end()){

							ans = max(ans,count+info[p].num);
							MAP[v_a[r]] = info[p].num;
						}else{

							if(fabs(v_a[r]-at->first) < EPS){

								ans = max(ans,count+at->second+info[p].num);
								at->second += info[p].num;
							}else{
								ans = max(ans,count+info[p].num);
								MAP[v_a[r]] = info[p].num;
							}
						}
					}
				}

			}else{

				//連立方程式を解く
				count = info[i].num+info[k].num;
				MAP.clear();

				//点aを原点に固定する
				for(int p = 0; p < N; p++){

					work_int_point[p].int_x = int_point[p].int_x-int_point[a].int_x;
					work_int_point[p].int_y = int_point[p].int_y-int_point[a].int_y;
					work_int_vec[p].int_x = int_vec[p].int_x-int_vec[a].int_x;
					work_int_vec[p].int_y = int_vec[p].int_y-int_vec[a].int_y;

					work_point[p] = point[p]-point[a];
					work_vec[p] = vec[p]-vec[a];
				}

				count = 2;

				Line line1,line2,line3;
				Point p1,p2,p3;

				for(int p = 0; p < info.size(); p++){
					if(p == i || p == k)continue;

					vector<double> tmp_vec;

					//aとpを結ぶ線は常に原点線なので、bとpについてのみ見れば良い
					tmp_vec = calc_equation(b,info[p].index);
					if(tmp_vec.size() == 1 && fabs(tmp_vec[0]+HUGE_NUM) < EPS){
						//判別式の係数が全て0は重なる
						count += info[p].num;
						continue;
					}

					if(tmp_vec.size() == 0)continue;

					for(int q = 0; q < tmp_vec.size(); q++){

						double T = tmp_vec[q];

						//aとbが重なる時刻はSKIP(異なる[原点を通る直線]を同一と見なしてしまうため)
						Point tmp_p = calc_T_point(b,T);
						if(isSame(tmp_p,work_point[a])){
							ans = max(ans,3);
							continue;
						}

						auto at = MAP.lower_bound(T-EPS);

						if(at == MAP.end()){

							ans = max(ans,count+info[p].num);
							MAP[T] = info[p].num;
						}else{

							if(fabs(T-at->first) < EPS){

								ans = max(ans,count+at->second+info[p].num);
								at->second += info[p].num;
							}else{
								ans = max(ans,count+info[p].num);
								MAP[T] = info[p].num;
							}
						}
					}
				}
			}
		}
	}

	printf("%d\n",ans);

	return 0;
}
accuracy: 1
time_ms: 260
memory_kb: 3260
final_rank: 4

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 1000000000000000000
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;



#define SIZE 205

struct Point{
	Point(double arg_x,double arg_y){
		x = arg_x;
		y = arg_y;
	}

	Point(){
		x = y = 0.0;
	}

	Point operator + (Point p){ return Point(x+p.x,y+p.y); }
	Point operator - (Point p){ return Point(x-p.x,y-p.y);}
	Point operator * (double a){ return Point(a*x,a*y); }
	Point operator / (double a){ return Point(x/a,y/a); }

	double abs(){ return sqrt(norm()); }
	double norm(){ return x*x + y*y; }

	bool operator<(const Point &p) const{
		return x != p.x? x < p.x: y < p.y;
	}

	bool operator == (const Point &p) const{
		return fabs(x-p.x) < EPS && fabs(y-p.y) < EPS;
	}


	void debug(){

		printf("(%.3lf,%.3lf)\n",x,y);
	}

	double x,y;
};

struct Data{

	int int_x,int_y;
};

struct Info{
	Info(int arg_index,int arg_num){
		index = arg_index;
		num = arg_num;
	}
	int index,num;
};

struct Pos{

	double slope,add;
};

typedef Point Vector;

struct Line{
	Line(){

	}
	Line(Point a,Point b){
		p[0] = a;
		p[1] = b;
	}
	/*void outPut(){

		printf("(%.3lf,%.3lf)-(%.3lf,%.3lf)\n",p[0].x,p[0].y,p[1].x,p[1].y);
	}*/
	Point p[2];
};

int N;
double vec_slope[SIZE],work_vec_slope[SIZE];
bool check[SIZE],work[SIZE];
Data int_point[SIZE],int_vec[SIZE],work_int_point[SIZE],work_int_vec[SIZE];
Point point[SIZE],vec[SIZE],work_point[SIZE],work_vec[SIZE];
vector<Info> info;
map<double,int> MAP;


double calc_slope(Line A){

	if(fabs(A.p[0].x-A.p[1].x) < EPS){

		return DBL_MAX;

	}else if(fabs(A.p[0].y-A.p[1].y) < EPS){

		return 0;

	}else{

		return (A.p[1].y-A.p[0].y)/(A.p[1].x-A.p[0].x);
	}
}

//傾きと切片を計算する関数
Pos calc_pos(Line A){

	double slope = calc_slope(A);
	double add;

	if(fabs(slope-DBL_MAX) < EPS){

		add = 0;

	}else if(fabs(slope) < EPS){

		add = A.p[0].y;

	}else{

		add = A.p[0].y-slope*A.p[0].x;
	}

	Pos ret;
	ret.slope = slope;
	ret.add = add;

	return ret;
}

//点iと点kが原点線上に並ぶ時刻を求める
vector<double> calc_equation(int i,int k){

	vector<double> ret;

	ll int_a = work_int_point[i].int_x,int_b = work_int_point[i].int_y,int_p = work_int_vec[i].int_x,int_q = work_int_vec[i].int_y;
	ll int_c = work_int_point[k].int_x,int_d = work_int_point[k].int_y,int_r = work_int_vec[k].int_x,int_s = work_int_vec[k].int_y;
	double a = work_point[i].x,b=work_point[i].y,p = work_vec[i].x,q = work_vec[i].y;
	double c = work_point[k].x,d=work_point[k].y,r = work_vec[k].x,s = work_vec[k].y;

	//printf("int_p:%lld int_s:%lld int_q:%lld int_r:%lld\n",int_p,int_s,int_q,int_r);

	ll int_A = int_p*int_s-int_q*int_r;
	ll int_B = int_a*int_s+int_d*int_p-(int_b*int_r+int_c*int_q);
	ll int_C = int_a*int_d-int_b*int_c;
	ll int_D = int_B*int_B-4*int_A*int_C;

	double A = p*s-q*r;
	double B = a*s+d*p-(b*r+c*q);
	double C = a*d-b*c;
	double D = B*B-4*A*C;

	if(int_A == 0){
		if(int_B == 0){
			if(int_C == 0){
				//printf("int_Cが0\n");
				ret.push_back(-HUGE_NUM);
			}
			//printf("int_Cは0でない\n");
			return ret;
		}
		//printf("int_Bが0ではない\n");
		double tmp_t = (-C/B);
		if(tmp_t > 0){

			ret.push_back(tmp_t);
		}
		return ret;
	}
	if(int_D < 0){

		return ret;

	}else{

		double t1 = (-B+sqrt(D))/(2*A),t2 = (-B-sqrt(D))/(2*A);

		if(int_D == 0){

			if(t1 >= 0){

				ret.push_back(t1);
			}
			return ret;
		}else{

			if(t1 >= 0){

						ret.push_back(t1);
					}
					return ret;


			if(t2 >= 0){

				ret.push_back(t2);
			}
			return ret;
		}
	}
}

bool is_same_vec(int i,int k){

	if(int_vec[i].int_x==int_vec[k].int_x && int_vec[i].int_y == int_vec[k].int_y){

		return true;
	}else{

		return false;
	}
}

bool is_rev_vec(int i,int k){

	if(int_vec[i].int_x==-int_vec[k].int_x && int_vec[i].int_y == -int_vec[k].int_y){

		return true;

	}else{

		return false;
	}
}

double norm(Vector a){
	return a.x*a.x+a.y*a.y;
}

double abs(Vector a){
	return sqrt(norm(a));
}

Point calc_T_point(int index,double T){

	Point ret = Point(work_point[index].x+work_vec[index].x*T,work_point[index].y+work_vec[index].y*T);
	return ret;
}

bool isSame(Point a,Point b){

	if(abs(a-b) < EPS){

		return true;
	}else{

		return false;
	}
}


int main(){

	scanf("%d",&N);

	for(int i = 0; i < N; i++){

		scanf("%d %d %d %d",&int_point[i].int_x,&int_point[i].int_y,&int_vec[i].int_x,&int_vec[i].int_y);
		point[i].x = int_point[i].int_x;
		point[i].y = int_point[i].int_y;
		vec[i].x = int_vec[i].int_x;
		vec[i].y = int_vec[i].int_y;

		if(int_vec[i].int_x == 0){

			vec_slope[i] = DBL_MAX;

		}else{

			vec_slope[i] = vec[i].y/vec[i].x;
		}
	}

	if(N <= 2){

		printf("%d\n",N);
		return 0;
	}

	//点の重複を除く
	for(int i = 0; i < N; i++){

		check[i] = false;
	}

	for(int i = 0; i < N; i++){
		if(check[i])continue;

		int num = 1;

		for(int k = i+1; k < N; k++){
			if(int_point[i].int_x == int_point[k].int_x && int_point[i].int_y == int_point[k].int_y
					&& int_vec[i].int_x == int_vec[k].int_x && int_vec[i].int_y == int_vec[k].int_y){
				num++;
				check[k] = true;
			}
		}
		info.push_back(Info(i,num));
	}

	if(info.size() <= 2){

		printf("%d\n",N);
		return 0;
	}

	int a,b;
	Line tmp_line;
	Pos pos;

	int ans = 0,count;

	//printf("info.size():%lld\n",info.size());

	for(int i = 0; i < info.size()-1; i++){
		a = info[i].index;
		for(int k = i+1; k < info.size(); k++){
			b = info[k].index;

			//point[a].debug();
			//point[b].debug();

			tmp_line.p[0] = point[a],tmp_line.p[1] = point[b];
			//時刻0の直線の傾きと切片を求める
			pos = calc_pos(tmp_line);

			//時刻0の,a-b直線上の個数を数える
			count = info[i].num+info[k].num;
			for(int p = 0; p < info.size(); p++){
				if(p == i || p == k)continue;

				if(fabs(pos.slope-DBL_MAX) < EPS){ //垂直

					if(int_point[info[p].index].int_x == int_point[a].int_x){
						count += info[p].num;
					}

				}else{

					if(fabs(point[info[p].index].y-(pos.slope*point[info[p].index].x+pos.add)) < EPS){
						count += info[p].num;
					}
				}
			}

			ans = max(ans,count);
			//printf("時刻0: count:%d\n",count);

			//2点を通る直線の傾きと切片が永遠に同じ場合
			if((is_same_vec(a,b)||is_rev_vec(a,b))&&fabs(pos.slope-fabs(vec_slope[a])) < EPS){

				//printf("永遠に々\n");

				for(int p = 0; p < N; p++)work[p] = false;

				count = info[i].num+info[k].num;

				//同一直線上にある、他の同一直線上を動く点を探す(これらも永遠に当該直線状に存在する)
				for(int p = 0; p < info.size(); p++){
					if(p == i || p == k)continue;

					if(fabs(pos.slope-DBL_MAX) < EPS){ //垂直

						if(int_point[info[p].index].int_x == int_point[a].int_x && int_vec[info[p].index].int_x == 0){

							count += info[p].num;
							work[p] = true;
						}

					}else{

						if(fabs(point[info[p].index].y-(pos.slope*point[info[p].index].x+pos.add)) < EPS &&
								(is_same_vec(a,info[p].index)||is_rev_vec(a,info[p].index))){

							count += info[p].num;
							work[p] = true;
						}
					}
				}

				MAP.clear();
				ans = max(ans,count);

				//点aを原点に固定する
				for(int p = 0; p < N; p++){
					if(p == a)continue;

					work_int_point[p].int_x = int_point[p].int_x-int_point[a].int_x;
					work_int_point[p].int_y = int_point[p].int_y-int_point[a].int_y;
					work_int_vec[p].int_x = int_vec[p].int_x-int_vec[a].int_x;
					work_int_vec[p].int_y = int_vec[p].int_y-int_vec[a].int_y;

					work_point[p] = point[p]-point[a];
					work_vec[p] = vec[p]-vec[a];
				}

				for(int p = 0; p < info.size(); p++){
					if(p == i || p == k || work[p])continue;

					vector<double> v_a;

					v_a =  calc_equation(info[p].index,a);
					if(v_a.size() == 0)continue;

					if(v_a.size() == 1 && fabs(v_a[0]+HUGE_NUM) < EPS){

						count++;
						continue;
					}

					for(int r = 0; r < v_a.size(); r++){

						auto at = MAP.lower_bound(v_a[r]-EPS);
						if(at == MAP.end()){

							ans = max(ans,count+info[p].num);
							MAP[v_a[r]] = info[p].num;
						}else{

							if(fabs(v_a[r]-at->first) < EPS){

								ans = max(ans,count+at->second+info[p].num);
								at->second += info[p].num;
							}else{
								ans = max(ans,count+info[p].num);
								MAP[v_a[r]] = info[p].num;
							}
						}
					}
				}

			}else if(is_same_vec(a,b)){ //2点の方向ベクトルが同じ場合

				//printf("平行移動\n");

				//点aを原点に固定する:点aと点bを通る直線は永遠に変わらない
				for(int p = 0; p < N; p++){

					work_int_point[p].int_x = int_point[p].int_x-int_point[a].int_x;
					work_int_point[p].int_y = int_point[p].int_y-int_point[a].int_y;
					work_int_vec[p].int_x = int_vec[p].int_x-int_vec[a].int_x;
					work_int_vec[p].int_y = int_vec[p].int_y-int_vec[a].int_y;

					work_point[p] = point[p]-point[a];
					work_vec[p] = vec[p]-vec[a];

					if(fabs(work_vec[p].x) < EPS){

						work_vec_slope[p] = DBL_MAX;
					}else{

						work_vec_slope[p] = work_vec[p].y/work_vec[p].x;
					}
				}

				//傾きを再度計算
				tmp_line.p[0] = work_point[a],tmp_line.p[1] = work_point[b];
				pos = calc_pos(tmp_line);

				for(int p = 0; p < info.size(); p++)work[p] = false;

				count = info[i].num+info[k].num;

				//同一直線上にある、他の同一直線上を動く点を探す
				for(int p = 0; p < info.size(); p++){
					if(p == i || p == k)continue;

					if(fabs(pos.slope-DBL_MAX) < EPS){ //垂直
						//x座標がaと同じで左右方向に動かない
						if(work_int_point[info[p].index].int_x == work_int_point[a].int_x && work_int_vec[info[p].index].int_x == 0){

							count += info[p].num;
							work[p] = true;
						}

					}else{

						if(fabs(work_point[info[p].index].y-(pos.slope*work_point[info[p].index].x+pos.add)) < EPS && //原点線上に存在
								(fabs(pos.slope-fabs(work_vec_slope[info[p].index])) < EPS)){ //かつ、傾きの絶対値が原点線と同じ

							count += info[p].num;
							work[p] = true;
						}
					}
				}

				MAP.clear();
				ans = max(ans,count);

				for(int p = 0; p < info.size(); p++){
					if(p == i || p == k || work[p])continue;

					vector<double> v_a;

					v_a =  calc_equation(b,info[p].index);
					if(v_a.size() == 0)continue;
					if(v_a.size() == 1 && fabs(v_a[0]+HUGE_NUM) < EPS){

						count++;
						continue;
					}

					for(int r = 0; r < v_a.size(); r++){

						auto at = MAP.lower_bound(v_a[r]-EPS);
						if(at == MAP.end()){

							ans = max(ans,count+info[p].num);
							MAP[v_a[r]] = info[p].num;
						}else{

							if(fabs(v_a[r]-at->first) < EPS){

								ans = max(ans,count+at->second+info[p].num);
								at->second += info[p].num;
							}else{
								ans = max(ans,count+info[p].num);
								MAP[v_a[r]] = info[p].num;
							}
						}
					}
				}

			}else{

				//printf("その他\n");

				//連立方程式を解く
				count = info[i].num+info[k].num;
				MAP.clear();

				//point[a].debug();
				//point[b].debug();

				//点aを原点に固定する
				for(int p = 0; p < N; p++){

					work_int_point[p].int_x = int_point[p].int_x-int_point[a].int_x;
					work_int_point[p].int_y = int_point[p].int_y-int_point[a].int_y;
					work_int_vec[p].int_x = int_vec[p].int_x-int_vec[a].int_x;
					work_int_vec[p].int_y = int_vec[p].int_y-int_vec[a].int_y;

					work_point[p] = point[p]-point[a];
					work_vec[p] = vec[p]-vec[a];
				}

				count = 2;

				Line line1,line2,line3;
				Point p1,p2,p3;

				for(int p = 0; p < info.size(); p++){
					if(p == i || p == k)continue;

					//point[info[p].index].debug();

					vector<double> tmp_vec;

					//printf("info[%d].index:%d\n",p,info[p].index);

					//aとpを結ぶ線は常に原点線なので、bとpについてのみ見れば良い
					tmp_vec = calc_equation(b,info[p].index);
					if(tmp_vec.size() == 1 && fabs(tmp_vec[0]+HUGE_NUM) < EPS){
						//printf("判別式all 0");
						count++;
						continue;
					}
					/*for(int d = 0; d < tmp_vec.size(); d++){
						printf("vec_a[%d]:%.3lf\n",d,tmp_vec[d]);
					}*/

					if(tmp_vec.size() == 0)continue;

					for(int q = 0; q < tmp_vec.size(); q++){

						double T = tmp_vec[q];
						//printf("T:%.3lf\n",T);

						//aとbが重なる時刻はSKIP
						Point tmp_p = calc_T_point(b,T);
						if(isSame(tmp_p,work_point[a])){
							ans = max(ans,3);
							continue;
						}

						auto at = MAP.lower_bound(T-EPS);

						if(at == MAP.end()){

							ans = max(ans,count+info[p].num);
							MAP[T] = info[p].num;
						}else{

							if(fabs(T-at->first) < EPS){

								ans = max(ans,count+at->second+info[p].num);
								at->second += info[p].num;
							}else{
								ans = max(ans,count+info[p].num);
								MAP[T] = info[p].num;
							}
						}
					}
				}
			}
		}
	}

	printf("%d\n",ans);

	return 0;
}
accuracy: 1
time_ms: 260
memory_kb: 3252
final_rank: 3

code_snippet: #include "bits/stdc++.h"
#include<unordered_map>
#include<unordered_set>
#pragma warning(disable:4996)
using namespace std;
using ld=long double;
const ld eps=1e-9;

struct apple {
	pair<int ,int>coors;
	pair<int ,int>v;
};

apple operator-(const apple&r, const apple&l) {
	apple ans;
	ans.coors.first=r.coors.first-l.coors.first;
	ans.coors.second=r.coors.second-l.coors.second;
	ans.v.first=r.v.first-l.v.first;
	ans.v.second=r.v.second-l.v.second;
	return ans;
}
vector<ld>quad_equa(ld a, ld b, ld c) {
	if (abs(a) < eps) {
		if (abs(b) < eps) {
			return vector<ld>();
		}
		else {
			return vector<ld>{-c / b};
		}
	}
	ld root = b*b - 4 * a*c;
	if (abs(root) < eps) {
		ld ans = -b / (2 * a);
		return vector<ld>(1, ans);
	}
	else if (root > 0) {
		ld ans = -b / (2 * a);
		vector<ld>anss(2);
		anss[0] = ans + sqrt(root) / (2 * a);
		anss[1] = ans - sqrt(root) / (2 * a);
		if (anss[0] > anss[1])swap(anss[0], anss[1]);
		return anss;
	}
	else {
		return vector<ld>();
	}
}
vector<pair<ld,ld>> solve(vector<apple>apples) {
	apple apple_1=apples[1]-apples[0];
	apple apple_2=apples[2]-apples[0];

	ld two=apple_1.v.first*apple_2.v.second-(apple_1.v.second*apple_2.v.first);

	ld one=apple_1.v.first* (apple_2.coors.second) + apple_2.v.second* (apple_1.coors.first)-
		apple_2.v.first*(apple_1.coors.second)-apple_1.v.second*(apple_2.coors.first);

	ld zero=(apple_1.coors.first)*(apple_2.coors.second)
		-(apple_1.coors.second)*(apple_2.coors.first);
	zero=zero;

	auto v=quad_equa(two,one,zero);

	vector<pair<ld,ld>>ans;
	for (auto a : v) {
		if (a > -eps) {
			ans.push_back(make_pair(a-eps,a+eps));
		}
	}
	if (abs(two) < eps&&abs(one) < eps&&abs(zero) < eps) {
		ans.emplace_back(-1e8,1e8);
	}
	return ans;

}
class Compress {
public:
	bool operator()(const ld&l, const ld&r)const {
		return l+eps<r;
	}
};
int main() {
	int N;cin>>N;
	vector<pair<apple,int>>apples;
	for (int i = 0; i < N; ++i) {
		int a,b,c,d;cin>>a>>b>>c>>d;

		apple n_apple{ make_pair(a,b),make_pair(c,d) };
		auto it = find_if(apples.begin(), apples.end(), [&](const pair<apple,int>&l) {
			return l.first.coors==n_apple.coors&&l.first.v==n_apple.v;
		});
		if (it == apples.end()) {
			apples.push_back(make_pair(apple{ make_pair(a,b),make_pair(c,d) },1));
		}
		else {
			it->second++;
		}

	}
	

	int ans=0;

	set<ld,Compress>aset;
	for (int i = 0; i < apples.size(); ++i) {
		for (int j = 0; j < apples.size(); ++j) {
			if(i==j)continue;

			auto apple_i=apples[i].first;
			auto apple_j=apples[j].first;
			ld time=-2;
			
				
				int dx=apple_i.coors.first-apple_j.coors.first;
				int dy=apple_i.coors.second-apple_j.coors.second;
				dx=-dx;
				dy=-dy;
				int dvx=apple_i.v.first-apple_j.v.first;
				int dvy=apple_i.v.second-apple_j.v.second;

				bool ok=true;

				ld time1=-1;
				if (dx >= 0 && dvx > 0) {
					time1=ld(dx)/dvx;
				}
				else if (dx == 0 && dvx == 0) {
					time1=1e9;
				}
				else if (dx <= 0 && dvx < 0) {
					time1=ld(dx)/dvx;
				}
				else {
					ok=false;
				}
				ld time2=-1;
				if (dy*dvy > 0) {
					time2=ld(dy)/dvy;
				}
				else if (dy == 0 && dvy == 0) {
					time2=1e9;
				}
				else if (dy == 0 && dvy != 0) {
					time2=0;
				}
				else {
					ok=false;
				}
				if (ok) {
					if(time1>1e8)time1=time2;
					if(time2>1e8)time2=time1;

					if(abs(time1-time2)<eps)time=time1;
				}
				aset.emplace(time);

			map < ld, int, Compress > mp;
			if (time > -eps) {
				mp[time-2*eps]-=1000;
				mp[time+2*eps]+=1000;
			}
			for (int k = 0; k < apples.size(); ++k) {
				if(i==k||j==k)continue;
				auto apple_k=apples[k].first;

				auto v = solve(vector<apple>{apple_i, apple_j, apple_k});

				for (auto p : v) {

					mp[p.first] += apples[k].second;
					mp[p.second] -= apples[k].second;
				}

			}
			mp[1]+=0;
			int sum=apples[i].second+apples[j].second;
			for (auto m : mp) {
				if (m.first > -eps) {
					ans=max(ans,sum);
				}
				sum+=m.second;
				if (m.first >= -eps) {
					ans = max(ans, sum);
					
				}
			}
		}
	}

	if (apples.size() <=2) {
		ans=N;
	}
	cout<<ans<<endl;
	return 0;
}
accuracy: 0.23076923076923078
time_ms: 30
memory_kb: 3088
final_rank: 17

code_snippet: #include "bits/stdc++.h"
#include<unordered_map>
#include<unordered_set>
#pragma warning(disable:4996)
using namespace std;
using ld=long double;
const ld eps=1e-9;

struct apple {
	pair<int ,int>coors;
	pair<int ,int>v;
};

apple operator-(const apple&r, const apple&l) {
	apple ans;
	ans.coors.first=r.coors.first-l.coors.first;
	ans.coors.second=r.coors.second-l.coors.second;
	ans.v.first=r.v.first-l.v.first;
	ans.v.second=r.v.second-l.v.second;
	return ans;
}
vector<ld>quad_equa(ld a, ld b, ld c) {
	if (abs(a) < eps) {
		if (abs(b) < eps) {
			return vector<ld>();
		}
		else {
			return vector<ld>{-c / b};
		}
	}
	ld root = b*b - 4 * a*c;
	if (abs(root) < eps) {
		ld ans = -b / (2 * a);
		return vector<ld>(1, ans);
	}
	else if (root > 0) {
		ld ans = -b / (2 * a);
		vector<ld>anss(2);
		anss[0] = ans + sqrt(root) / (2 * a);
		anss[1] = ans - sqrt(root) / (2 * a);
		if (anss[0] > anss[1])swap(anss[0], anss[1]);
		return anss;
	}
	else {
		return vector<ld>();
	}
}
vector<pair<ld,ld>> solve(vector<apple>apples) {
	apple apple_1=apples[1]-apples[0];
	apple apple_2=apples[2]-apples[0];

	ld two=apple_1.v.first*apple_2.v.second-(apple_1.v.second*apple_2.v.first);

	ld one=apple_1.v.first* (apple_2.coors.second) + apple_2.v.second* (apple_1.coors.first)-
		apple_2.v.first*(apple_1.coors.second)-apple_1.v.second*(apple_2.coors.first);

	ld zero=(apple_1.coors.first)*(apple_2.coors.second)
		-(apple_1.coors.second)*(apple_2.coors.first);
	zero=zero;

	auto v=quad_equa(two,one,zero);

	vector<pair<ld,ld>>ans;
	for (auto a : v) {
		if (a > -eps) {
			ans.push_back(make_pair(a-eps,a+eps));
		}
	}
	if (abs(two) < eps&&abs(one) < eps&&abs(zero) < eps) {
		ans.emplace_back(-1e8,1e8);
	}
	return ans;

}
class Compress {
public:
	bool operator()(const ld&l, const ld&r)const {
		return l+eps<r;
	}
};
int main() {
	int N;cin>>N;
	vector<pair<apple,int>>apples;
	for (int i = 0; i < N; ++i) {
		int a,b,c,d;cin>>a>>b>>c>>d;

		apple n_apple{ make_pair(a,b),make_pair(c,d) };
		auto it = find_if(apples.begin(), apples.end(), [&](const pair<apple,int>&l) {
			return l.first.coors==n_apple.coors&&l.first.v==n_apple.v;
		});
		if (it == apples.end()) {
			apples.push_back(make_pair(apple{ make_pair(a,b),make_pair(c,d) },1));
		}
		else {
			it->second++;
		}

	}
	

	int ans=0;

	set<ld,Compress>aset;
	for (int i = 0; i < apples.size(); ++i) {
		for (int j = 0; j < apples.size(); ++j) {
			if(i==j)continue;

			auto apple_i=apples[i].first;
			auto apple_j=apples[j].first;
			ld time=-2;
			
				
				int dx=apple_i.coors.first-apple_j.coors.first;
				int dy=apple_i.coors.second-apple_j.coors.second;
				dx=-dx;
				dy=-dy;
				int dvx=apple_i.v.first-apple_j.v.first;
				int dvy=apple_i.v.second-apple_j.v.second;

				bool ok=true;

				ld time1=-1;
				if (dx >= 0 && dvx > 0) {
					time1=ld(dx)/dvx;
				}
				else if (dx == 0 && dvx == 0) {
					time1=1e9;
				}
				else if (dx <= 0 && dvx < 0) {
					time1=ld(dx)/dvx;
				}
				else {
					ok=false;
				}
				ld time2=-1;
				if (dy*dvy > 0) {
					time2=ld(dy)/dvy;
				}
				else if (dy == 0 && dvy == 0) {
					time2=1e9;
				}
				else if (dy == 0 && dvy != 0) {
					time2=0;
				}
				else {
					ok=false;
				}
				if (ok) {
					if(time1>1e8)time1=time2;
					if(time2>1e8)time2=time1;

					if(abs(time1-time2)<eps)time=time1;
				}
				aset.emplace(time);

			map < ld, int, Compress > mp;
			if (time > -eps) {
				mp[time-2*eps]-=1000;
				mp[time+2*eps]+=1000;
			}
			for (int k = 0; k < apples.size(); ++k) {
				if(i==k||j==k)continue;
				auto apple_k=apples[k].first;

				auto v = solve(vector<apple>{apple_i, apple_j, apple_k});

				for (auto p : v) {

					mp[p.first] += apples[k].second;
					mp[p.second] -= apples[k].second;
				}

			}
			mp[1]+=0;
			int sum=apples[i].second+apples[j].second;
			for (auto m : mp) {
				if (m.first > -eps) {
					ans=max(ans,sum);
				}
				sum+=m.second;
				if (m.first >= -eps) {
					ans = max(ans, sum);
					
				}
			}
		}
	}

	if (apples.size() <=2) {
		ans=N;
	}else if (aset.size() == 1 && *aset.begin() > -1) {
		ans=N;
	}
	cout<<ans<<endl;
	return 0;
}
accuracy: 1
time_ms: 1990
memory_kb: 3164
final_rank: 6

code_snippet: #include "bits/stdc++.h"
#include<unordered_map>
#include<unordered_set>
#pragma warning(disable:4996)
using namespace std;
using ld=long double;
const ld eps=1e-9;

struct apple {
	pair<int ,int>coors;
	pair<int ,int>v;
};

apple operator-(const apple&r, const apple&l) {
	apple ans;
	ans.coors.first=r.coors.first-l.coors.first;
	ans.coors.second=r.coors.second-l.coors.second;
	ans.v.first=r.v.first-l.v.first;
	ans.v.second=r.v.second-l.v.second;
	return ans;
}
vector<ld>quad_equa(ld a, ld b, ld c) {
	if (abs(a) < eps) {
		if (abs(b) < eps) {
			return vector<ld>();
		}
		else {
			return vector<ld>{-c / b};
		}
	}
	ld root = b*b - 4 * a*c;
	if (abs(root) < eps) {
		ld ans = -b / (2 * a);
		return vector<ld>(1, ans);
	}
	else if (root > 0) {
		ld ans = -b / (2 * a);
		vector<ld>anss(2);
		anss[0] = ans + sqrt(root) / (2 * a);
		anss[1] = ans - sqrt(root) / (2 * a);
		if (anss[0] > anss[1])swap(anss[0], anss[1]);
		return anss;
	}
	else {
		return vector<ld>();
	}
}
vector<pair<ld,ld>> solve(vector<apple>apples) {
	apple apple_1=apples[1]-apples[0];
	apple apple_2=apples[2]-apples[0];

	ld two=apple_1.v.first*apple_2.v.second-(apple_1.v.second*apple_2.v.first);

	ld one=apple_1.v.first* (apple_2.coors.second) + apple_2.v.second* (apple_1.coors.first)-
		apple_2.v.first*(apple_1.coors.second)-apple_1.v.second*(apple_2.coors.first);

	ld zero=(apple_1.coors.first)*(apple_2.coors.second)
		-(apple_1.coors.second)*(apple_2.coors.first);
	zero=zero;

	auto v=quad_equa(two,one,zero);

	vector<pair<ld,ld>>ans;
	for (auto a : v) {
		if (a > -eps) {
			ans.push_back(make_pair(a-eps,a+eps));
		}
	}
	if (abs(two) < eps&&abs(one) < eps&&abs(zero) < eps) {
		ans.emplace_back(-1e8,1e8);
	}
	return ans;

}
class Compress {
public:
	bool operator()(const ld&l, const ld&r)const {
		return l+eps<r;
	}
};
int main() {
	int N;cin>>N;
	vector<pair<apple,int>>apples;
	for (int i = 0; i < N; ++i) {
		int a,b,c,d;cin>>a>>b>>c>>d;

		apple n_apple{ make_pair(a,b),make_pair(c,d) };
		auto it = find_if(apples.begin(), apples.end(), [&](const pair<apple,int>&l) {
			return l.first.coors==n_apple.coors&&l.first.v==n_apple.v;
		});
		if (it == apples.end()) {
			apples.push_back(make_pair(apple{ make_pair(a,b),make_pair(c,d) },1));
		}
		else {
			it->second++;
		}

	}

	int ans=0;

	set<ld,Compress>aset;
	for (int i = 0; i < apples.size(); ++i) {
		for (int j = 0; j < apples.size(); ++j) {
			if(i==j)continue;

			auto apple_i=apples[i].first;
			auto apple_j=apples[j].first;
			ld time=-2;
			
				
				int dx=apple_i.coors.first-apple_j.coors.first;
				int dy=apple_i.coors.second-apple_j.coors.second;
				dx=-dx;
				dy=-dy;
				int dvx=apple_i.v.first-apple_j.v.first;
				int dvy=apple_i.v.second-apple_j.v.second;

				bool ok=true;

				ld time1=-1;
				if (dx >= 0 && dvx > 0) {
					time1=ld(dx)/dvx;
				}
				else if (dx == 0 && dvx == 0) {
					time1=1e9;
				}
				else if (dx <= 0 && dvx < 0) {
					time1=ld(dx)/dvx;
				}
				else {
					ok=false;
				}
				ld time2=-1;
				if (dy*dvy > 0) {
					time2=ld(dy)/dvy;
				}
				else if (dy == 0 && dvy == 0) {
					time2=1e9;
				}
				else if (dy == 0 && dvy != 0) {
					time2=0;
				}
				else {
					ok=false;
				}
				if (ok) {
					if(time1>1e8)time1=time2;
					if(time2>1e8)time2=time1;

					if(abs(time1-time2)<eps)time=time1;
				}
				aset.emplace(time);

			map < ld, int, Compress > mp;
			if (time > -eps) {
				mp[time-2*eps]-=1000;
				mp[time+2*eps]+=1000;
			}
			for (int k = 0; k < apples.size(); ++k) {
				if(i==k||j==k)continue;
				auto apple_k=apples[k].first;

				auto v = solve(vector<apple>{apple_i, apple_j, apple_k});

				for (auto p : v) {

					mp[p.first] += apples[k].second;
					mp[p.second] -= apples[k].second;
				}

			}
			mp[1]+=0;
			int sum=apples[i].second+apples[j].second;
			for (auto m : mp) {
				if (m.first > -eps) {
					ans=max(ans,sum);
				}
				sum+=m.second;
				if (m.first >= -eps) {
					ans = max(ans, sum);
					
				}
			}
		}
	}

	if (aset.size() == 1 && *aset.begin() > -1) {
		ans=N;
	}
	cout<<ans<<endl;
	return 0;
}
accuracy: 0.20512820512820512
time_ms: 20
memory_kb: 3108
final_rank: 18

code_snippet: #include "bits/stdc++.h"
#include<unordered_map>
#include<unordered_set>
#pragma warning(disable:4996)
using namespace std;
using ld=long double;
const ld eps=1e-9;

struct apple {
	pair<int ,int>coors;
	pair<int ,int>v;
};

apple operator-(const apple&l, const apple&r) {
	apple ans;
	ans.coors.first=r.coors.first-l.coors.first;
	ans.coors.second=r.coors.second-l.coors.second;
	ans.v.first=r.v.first-l.v.first;
	ans.v.second=r.v.second-l.v.second;
	return ans;
}

pair<ld,ld> solve(vector<apple>apples) {
	apple apple_1=apples[1]-apples[0];
	apple apple_2=apples[2]-apples[0];

	ld one=apple_1.v.first* (0.001*apple_2.v.second+apple_2.coors.second) + apple_2.v.second* (0.001*apple_1.v.first+apple_1.coors.first)-
		apple_2.v.first*(0.001*apple_1.v.second+apple_1.coors.second)-apple_1.v.second*(apple_2.v.first*0.001+apple_2.coors.first);

	ld zero=(0.001*apple_1.v.first+apple_1.coors.first)*(0.001*apple_2.v.second+apple_2.coors.second)
		-(0.001*apple_1.v.second+apple_1.coors.second)*(0.001*apple_2.v.first+apple_2.coors.first);
	zero=-zero;

	if (abs(one) < eps&&abs(zero) < eps) {
		return make_pair(-1e8,1e8);
	}
	else if (abs(one)<eps&&abs(zero)>=eps) {
		return make_pair(1e8,-1e8);
	}
	else {
		return make_pair(zero/one-eps,zero/one+eps);
	}

}
class Compress {
public:
	bool operator()(const ld&l, const ld&r)const {
		return l+eps<r;
	}
};
int main() {
	int N;cin>>N;
	vector<pair<apple,int>>apples;
	for (int i = 0; i < N; ++i) {
		int a,b,c,d;cin>>a>>b>>c>>d;

		apple n_apple{ make_pair(a,b),make_pair(c,d) };
		auto it = find_if(apples.begin(), apples.end(), [&](const pair<apple,int>&l) {
			return l.first.coors==n_apple.coors&&l.first.v==n_apple.v;
		});
		if (it == apples.end()) {
			apples.push_back(make_pair(apple{ make_pair(a,b),make_pair(c,d) },1));
		}
		else {
			it->second++;
		}

	}

	int ans=0;

	set<ld,Compress>aset;
	for (int i = 0; i < apples.size(); ++i) {
		for (int j = 0; j < apples.size(); ++j) {
			if(i==j)continue;

			auto apple_i=apples[i].first;
			auto apple_j=apples[j].first;
			ld time=-2;
			
				
				int dx=apple_i.coors.first-apple_j.coors.first;
				int dy=apple_i.coors.second-apple_j.coors.second;
				dx=-dx;
				dy=-dy;
				int dvx=apple_i.v.first-apple_j.v.first;
				int dvy=apple_i.v.second-apple_j.v.second;

				bool ok=true;

				ld time1=-1;
				if (dx >= 0 && dvx > 0) {
					time1=ld(dx)/dvx;
				}
				else if (dx == 0 && dvx == 0) {
					time1=1e9;
				}
				else if (dx <= 0 && dvx < 0) {
					time1=ld(dx)/dvx;
				}
				else {
					ok=false;
				}
				ld time2=-1;
				if (dy*dvy > 0) {
					time2=ld(dy)/dvy;
				}
				else if (dy == 0 && dvy == 0) {
					time2=1e9;
				}
				else if (dy == 0 && dvy != 0) {
					time2=0;
				}
				else {
					ok=false;
				}
				if (ok) {
					if(time1>1e8)time1=time2;
					if(time2>1e8)time2=time1;

					if(abs(time1-time2)<eps)time=time1;
				}
				aset.emplace(time);

			map < ld, int, Compress > mp;
			if (time > -eps) {
				mp[time-2*eps-0.001]-=1000;
				mp[time+2*eps-0.001]+=1000;
			}
			for (int k = 0; k < apples.size(); ++k) {
				if(i==k||j==k)continue;
				auto apple_k=apples[k].first;

				auto p = solve(vector<apple>{apple_i, apple_j, apple_k});

				mp[p.first]+=apples[k].second;
				mp[p.second]-=apples[k].second;

			}
			mp[1]+=0;
			int sum=apples[i].second+apples[j].second;
			for (auto m : mp) {
				sum+=m.second;
				if (m.first >= -eps) {
					ans = max(ans, sum);
					
				}
			}
		}
	}

	if (aset.size() == 1 && *aset.begin() > -1) {
		ans=N;
	}
	cout<<ans<<endl;
	return 0;
}
accuracy: 0.1282051282051282
time_ms: 20
memory_kb: 3112
final_rank: 19

code_snippet: #include "bits/stdc++.h"
#include<unordered_map>
#include<unordered_set>
#pragma warning(disable:4996)
using namespace std;
using ld=long double;
const ld eps=1e-9;

struct apple {
	pair<int ,int>coors;
	pair<int ,int>v;
};

apple operator-(const apple&l, const apple&r) {
	apple ans;
	ans.coors.first=r.coors.first-l.coors.first;
	ans.coors.second=r.coors.second-l.coors.second;
	ans.v.first=r.v.first-l.v.first;
	ans.v.second=r.v.second-l.v.second;
	return ans;
}

pair<ld,ld> solve(vector<apple>apples) {
	apple apple_1=apples[1]-apples[0];
	apple apple_2=apples[2]-apples[0];

	ld one=apple_1.v.first*apple_2.coors.second+apple_2.v.second*apple_1.coors.first-
		apple_2.v.first*apple_1.coors.second-apple_1.v.second*apple_2.coors.first;

	ld zero=apple_1.coors.first*apple_2.coors.second-apple_1.coors.second*apple_2.coors.first;
	zero=-zero;

	if (abs(one) < eps&&abs(zero) < eps) {
		return make_pair(-1e8,1e8);
	}
	else if (abs(one)<eps&&abs(zero)>=eps) {
		return make_pair(1e8,-1e8);
	}
	else {
		return make_pair(zero/one-eps,zero/one+eps);
	}

}
class Compress {
public:
	bool operator()(const ld&l, const ld&r)const {
		return l+eps<r;
	}
};
int main() {
	int N;cin>>N;
	vector<pair<apple,int>>apples;
	for (int i = 0; i < N; ++i) {
		int a,b,c,d;cin>>a>>b>>c>>d;

		apple n_apple{ make_pair(a,b),make_pair(c,d) };
		auto it = find_if(apples.begin(), apples.end(), [&](const pair<apple,int>&l) {
			return l.first.coors==n_apple.coors&&l.first.v==n_apple.v;
		});
		if (it == apples.end()) {
			apples.push_back(make_pair(apple{ make_pair(a,b),make_pair(c,d) },1));
		}
		else {
			it->second++;
		}

	}

	int ans=0;

	for (int i = 0; i < apples.size(); ++i) {
		for (int j = 0; j < apples.size(); ++j) {
			if(i==j)continue;

			auto apple_i=apples[i].first;
			auto apple_j=apples[j].first;

			ld time=-2;
			{
				
				int dx=apple_i.coors.first-apple_j.coors.first;
				int dy=apple_i.coors.second-apple_j.coors.second;

				int dvx=apple_i.v.first-apple_j.v.first;
				int dvy=apple_j.v.second=apple_j.v.second;

				bool ok=true;

				ld time1=-1;
				if (dx > 0 && dvx > 0) {
					time1=ld(dx)/dvx;
				}
				else if (dx == 0 && dvx == 0) {
					time1=1e9;
				}
				else if (dx < 0 && dvx < 0) {
					time1=ld(dx)/dvx;
				}
				else {
					ok=false;
				}
				ld time2=-1;
				if (dy*dvx > 0) {
					time2=ld(dy)/dvy;
				}
				else if (dy == 0 && dvy == 0) {
					time2=1e9;
				}
				else {
					ok=false;
				}
				if (ok) {
					if(time1>1e8)time1=time2;
					if(time2>1e8)time2=time1;

					if(abs(time1-time2)<eps)time=time1;
				}
			}

			map < ld, int, Compress > mp;
			if (time > -eps) {
				mp[time-2*eps]-=1000;
				mp[time+2*eps]+=1000;
			}
			for (int k = 0; k < apples.size(); ++k) {
				if(i==k||j==k)continue;
				auto apple_k=apples[k].first;

				auto p = solve(vector<apple>{apple_i, apple_j, apple_k});

				mp[p.first]+=apples[k].second;
				mp[p.second]-=apples[k].second;

			}
			int sum=apples[i].second+apples[j].second;
			for (auto m : mp) {
				sum+=m.second;
				if(m.first>=-eps)ans=max(ans,sum);
			}
		}
	}
	cout<<ans<<endl;
	return 0;
}
accuracy: 0.07692307692307693
time_ms: 30
memory_kb: 3104
final_rank: 20

code_snippet: #include<cstdio>
#include<utility>
#include<vector>
#include<cmath>
#include<algorithm>
 
using namespace std;
/*
typedef pair<int,int> P;
typedef pair<P,int> PP;
*/
 
typedef double Real;
 
const Real eps=1e-9;
 
template<class T> bool eq(T a,T b){
    return abs(a-b)<=eps;
}
 
template<class T> int sgn(T a){
    if(eq(a,0.0)) return 0;
    if(a>0) return 1;
    return -1;
}
 
int N;
int xs[220],ys[220],us[220],vs[220];
 
//map<PP,int> cnt;
 
vector<Real> vals;
int num;
 
void push(int a,int b,int c,int d,int e,int f,int g,int h){
    int A=c*h-d*g;
    int B=a*h+c*f-b*g-d*e;
    int C=a*f-b*e;
    if(A==0){
        if(B==0){
            if(C==0){
                num++;
            }
            return;
        }
        Real t=-(Real)C/B;
        if(sgn(t)>=0){
            vals.push_back(t);
        }
        return;
    }
    if(B*B-4*A*C<0){
        return;
    }
    if(B*B-4*A*C==0){
        Real t=-(Real)B/(A*2);
        if(sgn(t)>=0) vals.push_back(t);
        return;
    }
    Real s=sqrt(B*B-4*A*C);
    Real t1=(-B+s)/(A*2);
    if(sgn(t1)>=0) vals.push_back(t1);
    Real t2=(-B-s)/(A*2);
    if(sgn(t2)>=0) vals.push_back(t2);
}
 
void init(){
    vals.clear();
    num=0;
}
 
int solve(int id1,int id2){
//  printf("%d %d\n",id1,id2);
    init();
    int x1=xs[id1],y1=ys[id1],u1=us[id1],v1=vs[id1];
    int x2=xs[id2],y2=ys[id2],u2=us[id2],v2=vs[id2];
    for(int i=0;i<N;i++){
        if(i==id1||i==id2) continue;
        int x=xs[i],y=ys[i],u=us[i],v=vs[i];
//      printf("%d %d %d %d %d %d %d %d\n",x1-x,y1-y,u
        push(x1-x,y1-y,u1-u,v1-v,x2-x,y2-y,u2-u,v2-v);
//      printf("pushed %d\n",i);
    }
//  printf("c\n");
    int Ma=0;
    Real t;
    for(int i=0;i<vals.size();i++){
        Real v=vals[i];
        int tmp=0;
        if(eq(xs[id1]+us[id1]*v,xs[id2]+us[id2]*v)&&eq(ys[id1]+vs[id1]*v,ys[id2]+vs[id2]*v)) continue;
//      printf("%f\n",v);
        for(int j=i;j<vals.size();j++){
            if(eq(v,vals[j])){
                tmp++;
            }
        }
//      if(tmp+num+2==N){
//          printf("%d %d\n",id1,id2);
//          printf("%f %d\n",v,num);
//      for(int j=0;j<N;j++){
//          printf("%f %f\n",xs[j]+us[j]*v,ys[j]+vs[j]*v);
//      }
//      }
        Ma=max(Ma,tmp);
    }
//  printf("num=%d\n",num);
    return Ma+num+2;
}
 
bool all_same(){
    for(int i=0;i<N;i++) for(int j=i+1;j<N;j++){
        if(xs[i]!=xs[j]||ys[i]!=ys[j]||us[i]!=us[j]||vs[i]!=vs[j]){
            return false;
        }
    }
    return true;
}
 
Real get(int x1,int u1,int x2,int u2){
    if(u1==u2){
        if(x1==x2) return -1;
        else return -2;
    }
    return (Real)(x2-x1)/(u1-u2);
}
 
int main(){
    scanf("%d",&N);
    for(int i=0;i<N;i++){
        scanf("%d%d%d%d",xs+i,ys+i,us+i,vs+i);
    }
    if(N<=2){
        printf("%d\n",N);
        return 0;
    }
    if(all_same()){
        printf("%d\n",N);
        return 0;
    }
//  printf("a\n");
    bool flg=false;
    for(int i=0;i<N;i++) for(int j=i+1;j<N;j++){
        Real tx=get(xs[i],us[i],xs[j],us[j]);
        Real ty=get(ys[i],vs[i],ys[j],vs[j]);
        if(eq(tx,-2.0)||eq(ty,-2.0)) continue;
        if(eq(tx,-1.0)&&eq(ty,-1.0)) continue;
        Real t;
        if(eq(tx,-1.0)) t=ty;
        else t=tx;
        if(eq(tx,-1.0)==false&&eq(tx,t)==false) continue;
        if(eq(ty,-1.0)==false&&eq(ty,t)==false) continue;
        if(sgn(t)<0) continue;
        Real X=xs[0]+t*us[0];
        Real Y=ys[0]+t*vs[0];
        bool tmp=true;
        for(int k=0;k<N;k++){
            Real cx=xs[k]+t*us[k];
            Real cy=ys[k]+t*vs[k];
            if(eq(X,cx)==false||eq(Y,cy)==false){
                tmp=false;
            }
        }
        if(tmp) flg=true;
    }
//  printf("b\n");
    ed:;
    if(flg){
        printf("%d\n",N);
        return 0;
    }
    int ans=0;
//  printf("c\n");
    for(int i=0;i<N;i++) for(int j=i+1;j<N;j++){
        if(xs[i]==xs[j]&&ys[i]==ys[j]&&us[i]==us[j]&&vs[i]==vs[j]){
            continue;
        }
//      printf("a %d %d\n",i,j);
        int cur=solve(i,j);
        ans=max(ans,cur);
    }
//  printf("d\n");
    if(ans==0){
        printf("%d\n",N);
    }else{
        printf("%d\n",ans);
    }
    return 0;
}
accuracy: 1
time_ms: 270
memory_kb: 2788
final_rank: 1

code_snippet: #define _USE_MATH_DEFINES
#include <iostream>
#include <queue>
#include <vector>
#include <math.h>
#include <algorithm>
#include <iomanip>
#include <string>
#include <stack>
#include <cctype>
#include <cstdlib>
#include <tuple>
using namespace std;

#define INF (1 << 20)
#define EPS (1e-10)
#define EQ(a,b) (fabs((a)-(b)) < EPS)

int main(){
	int x[200], y[200], u[200], v[200];
	int n;
	int result = 0;
	int flg = 0;
	double ta = -1.0;
	cin >> n;
	if (n == 1 || n == 2) {
		cout << n << endl;
		return 0;
	}
	for (int i = 0; i < n; ++i) cin >> x[i] >> y[i] >> u[i] >> v[i];
	for (int i = 0; i < n; ++i) {
		for (int j = 0; j < n; ++j) {
			vector<tuple<double, double, double> > txyl;
			int cnt = 0;
			int xa = x[i] - x[j];
			int ya = y[i] - y[j];
			int ua = u[i] - u[j];
			int va = v[i] - v[j];
			if (xa == 0 && ya == 0 && ua == 0 && va == 0) continue;
			flg = 1;
			if (xa * va == ya * va) {
				double tt;
				if (xa != 0) tt = -1.0 * xa / ua;
				else tt = -1.0 * ya / va;
				if (tt >= 0) {
					for (int k = 0; k < n; ++k) {
						if (!EQ(x[0] + tt * u[0],x[k] + tt * u[k]) ||
								!EQ(y[0] + tt * v[0],y[k] + tt * v[k])) break;
						if (k == n-1) {
							cout << n << endl;
							return 0;
						}
					}
				}
			}
			for (int k = 0; k < n; ++k) {
				int flga = 0;
				int xb = x[i] - x[k];
				int yb = y[i] - y[k];
				int ub = u[i] - u[k];
				int vb = v[i] - v[k];
				double a = ua * vb - ub * va;
				double b = xa * vb + ua * yb - xb * va - ub * ya;
				double c = xa * yb - xb * ya;
				if (a == 0 && b == 0) {
					if (c == 0)	++cnt;
				} else if (a == 0) {
					double t = -c/b;
					if (!EQ(xa + t * ua,0) || !EQ(ya + t * va,0))
						txyl.push_back(make_tuple(t, xb + t * ub, yb + t * vb));
				} else {
					if (b * b - 4 * a * c < 0) continue;
					double temp;
					if (4 * a * c == 0) {
						temp = fabs(b);
					} else {
						temp = sqrt(b * b - 4 * a * c);
					}
					if (EQ(temp/a,0)) {
						double t = -b / 2.0 / a;
						if (!EQ(xa + t * ua,0) || !EQ(ya + t * va,0))
							txyl.push_back(make_tuple(t, xb + t * ub, yb + t * vb));
						continue;
					}
					double t = (-b + temp) / 2.0 / a;
					if (!EQ(xa + t * ua,0) || !EQ(ya + t * va,0))
						txyl.push_back(make_tuple(t, xb + t * ub, yb + t * vb));
					t = (-b - temp) / 2.0 / a;
					if (!EQ(xa + t * ua,0) || !EQ(ya + t * va,0))
						txyl.push_back(make_tuple(t, xb + t * ub, yb + t * vb));
				}
			}
			//if (count + cnt == n) result = n;
			sort(txyl.begin(), txyl.end());
			int kk = 0;
			while (kk < txyl.size() && get<0>(txyl[kk]) < 0) ++kk;
			int ccnt = 0;
			while (kk < txyl.size()) {
				double time = get<0>(txyl[kk]);
				int no_line = 0;
				for (int k = kk; k < txyl.size() && EQ(time,get<0>(txyl[k]));++k) {
					if (EQ(get<1>(txyl[k]),0) && EQ(get<2>(txyl[k]),0)) {
						++no_line;
					}
				}
				int max_group = 0;
				for (int l = kk; l < txyl.size() && EQ(time,get<0>(txyl[l])); ++l) {
					int num_group = 0;
					if (EQ(get<1>(txyl[l]),0) && EQ(get<2>(txyl[l]),0)) continue;
					for (int k = kk; k < txyl.size() && EQ(time,get<0>(txyl[k])); ++k) {
						if (EQ(get<1>(txyl[k]),0) && EQ(get<2>(txyl[k]),0)) continue;
						if (EQ(get<1>(txyl[l]) * get<2>(txyl[k]), get<1>(txyl[k]) * get<2>(txyl[l]))) {
							++num_group;
						}
					}
					max_group = max(max_group, num_group);
				}
				ccnt = max(ccnt, no_line + max_group);
				while (EQ(get<0>(txyl[kk]), time)) {
					++kk;
					if (kk == txyl.size()) break;
				}
			}
			//cout << "i:" << i << " j:" << j << " cnt:" << cnt << " ccnt:" << ccnt << " txyl:" << txyl.size() << endl;
			result = max(result, ccnt + cnt);
		}
	}
	if (flg == 0) {
		cout << n << endl;
	} else {
		cout << result << endl;
	}
	return 0;
}
accuracy: 1
time_ms: 600
memory_kb: 3140
final_rank: 5

code_snippet: #define _USE_MATH_DEFINES
#include <iostream>
#include <queue>
#include <vector>
#include <math.h>
#include <algorithm>
#include <iomanip>
#include <string>
#include <stack>
#include <cctype>
#include <cstdlib>
#include <tuple>
using namespace std;

#define INF (1 << 20)
#define EPS (1e-10)
#define EQ(a,b) (fabs((a)-(b)) < EPS)

int main(){
	int x[200], y[200], u[200], v[200];
	int n;
	int result = 0;
	int flg = 0;
	cin >> n;
	if (n == 1 || n == 2) {
		cout << n << endl;
		return 0;
	}
	for (int i = 0; i < n; ++i) cin >> x[i] >> y[i] >> u[i] >> v[i];
	for (int i = 0; i < n; ++i) {
		for (int j = 0; j < n; ++j) {
			vector<tuple<double, double, double> > txyl;
			int cnt = 0;
			int xa = x[i] - x[j];
			int ya = y[i] - y[j];
			int ua = u[i] - u[j];
			int va = v[i] - v[j];
			if (xa == 0 && ya == 0 && ua == 0 && va == 0) continue;
			flg = 1;
			int count = 0;
			for (int k = 0; k < n; ++k) {
				int flga = 0;
				int xb = x[i] - x[k];
				int yb = y[i] - y[k];
				int ub = u[i] - u[k];
				int vb = v[i] - v[k];
				double a = ua * vb - ub * va;
				double b = xa * vb + ua * yb - xb * va - ub * ya;
				double c = xa * yb - xb * ya;
				if (a == 0 && b == 0) {
					if (c == 0)	++cnt;
				} else if (a == 0) {
					double t = -c/b;
					if (!EQ(xa + t * ua,0) || !EQ(ya + t * va,0))
						txyl.push_back(make_tuple(t, xb + t * ub, yb + t * vb));
					else ++count;
				} else {
					if (b * b - 4 * a * c < 0) continue;
					double temp;
					if (4 * a * c == 0) {
						temp = fabs(b);
					} else {
						temp = sqrt(b * b - 4 * a * c);
					}
					if (EQ(temp/a,0)) {
						double t = -b / 2.0 / a;
					if (!EQ(xa + t * ua,0) || !EQ(ya + t * va,0))
					txyl.push_back(make_tuple(t, xb + t * ub, yb + t * vb));
					else ++count;
						continue;
					}
					double t = (-b + temp) / 2.0 / a;
					if (!EQ(xa + t * ua,0) || !EQ(ya + t * va,0))
					txyl.push_back(make_tuple(t, xb + t * ub, yb + t * vb));
					else {++count,++flga;}
					t = (-b - temp) / 2.0 / a;
					if (!EQ(xa + t * ua,0) || !EQ(ya + t * va,0))
					txyl.push_back(make_tuple(t, xb + t * ub, yb + t * vb));
					else {if (!flga)++count;}
				}
			}
			if (count == n) result = n;
			sort(txyl.begin(), txyl.end());
			int kk = 0;
			while (kk < txyl.size() && get<0>(txyl[kk]) < 0) ++kk;
			int ccnt = 0;
			while (kk < txyl.size()) {
				double time = get<0>(txyl[kk]);
				int no_line = 0;
				for (int k = kk; k < txyl.size() && EQ(time,get<0>(txyl[k]));++k) {
					if (EQ(get<1>(txyl[k]),0) && EQ(get<2>(txyl[k]),0)) {
						++no_line;
					}
				}
				int max_group = 0;
				for (int l = kk; l < txyl.size() && EQ(time,get<0>(txyl[l])); ++l) {
					int num_group = 0;
					if (EQ(get<1>(txyl[l]),0) && EQ(get<2>(txyl[l]),0)) continue;
					for (int k = kk; k < txyl.size() && EQ(time,get<0>(txyl[k])); ++k) {
						if (EQ(get<1>(txyl[k]),0) && EQ(get<2>(txyl[k]),0)) continue;
						if (EQ(get<1>(txyl[l]) * get<2>(txyl[k]), get<1>(txyl[k]) * get<2>(txyl[l]))) {
							++num_group;
						}
					}
					max_group = max(max_group, num_group);
				}
				ccnt = max(ccnt, no_line + max_group);
				while (EQ(get<0>(txyl[kk]), time)) {
					++kk;
					if (kk == txyl.size()) break;
				}
			}
			//cout << "i:" << i << " j:" << j << " cnt:" << cnt << " ccnt:" << ccnt << " txyl:" << txyl.size() << endl;
			result = max(result, ccnt + cnt);
		}
	}
	if (flg == 0) {
		cout << n << endl;
	} else {
	cout << result << endl;
	}
	return 0;
}
accuracy: 0.23076923076923078
time_ms: 10
memory_kb: 3096
final_rank: 15

code_snippet: #define _USE_MATH_DEFINES
#include <iostream>
#include <queue>
#include <vector>
#include <math.h>
#include <algorithm>
#include <iomanip>
#include <string>
#include <stack>
#include <cctype>
#include <cstdlib>
#include <tuple>
using namespace std;

#define INF (1 << 20)
#define EPS (1e-10)
#define EQ(a,b) (fabs((a)-(b)) < EPS)

int main(){
	int x[200], y[200], u[200], v[200];
	int n;
	int result = 0;
	int flg = 0;
	cin >> n;
	if (n == 1 || n == 2) {
		cout << n << endl;
		return 0;
	}
	for (int i = 0; i < n; ++i) cin >> x[i] >> y[i] >> u[i] >> v[i];
	for (int i = 0; i < n; ++i) {
		for (int j = 0; j < n; ++j) {
			vector<tuple<double, double, double> > txyl;
			int cnt = 0;
			int xa = x[i] - x[j];
			int ya = y[i] - y[j];
			int ua = u[i] - u[j];
			int va = v[i] - v[j];
			if (xa == 0 && ya == 0 && ua == 0 && va == 0) continue;
			flg = 1;
			for (int k = 0; k < n; ++k) {
				int xb = x[i] - x[k];
				int yb = y[i] - y[k];
				int ub = u[i] - u[k];
				int vb = v[i] - v[k];
				double a = ua * vb - ub * va;
				double b = xa * vb + ua * yb - xb * va - ub * ya;
				double c = xa * yb - xb * ya;
				if (a == 0 && b == 0) {
					if (c == 0)	++cnt;
				} else if (a == 0) {
					double t = -c/b;
					if (!EQ(xa + t * ua,0) || !EQ(ya + t * va,0))
						txyl.push_back(make_tuple(t, xb + t * ub, yb + t * vb));
				} else {
					if (b * b - 4 * a * c < 0) continue;
					double temp;
					if (4 * a * c == 0) {
						temp = fabs(b);
					} else {
						temp = sqrt(b * b - 4 * a * c);
					}
					if (EQ(temp/a,0)) {
						double t = -b / 2.0 / a;
					if (!EQ(xa + t * ua,0) || !EQ(ya + t * va,0))
					txyl.push_back(make_tuple(t, xb + t * ub, yb + t * vb));
						continue;
					}
					double t = (-b + temp) / 2.0 / a;
					if (!EQ(xa + t * ua,0) || !EQ(ya + t * va,0))
					txyl.push_back(make_tuple(t, xb + t * ub, yb + t * vb));
					t = (-b - temp) / 2.0 / a;
					if (!EQ(xa + t * ua,0) || !EQ(ya + t * va,0))
					txyl.push_back(make_tuple(t, xb + t * ub, yb + t * vb));
				}
			}
			sort(txyl.begin(), txyl.end());
			int kk = 0;
			while (kk < txyl.size() && get<0>(txyl[kk]) < 0) ++kk;
			int ccnt = 0;
			while (kk < txyl.size()) {
				double time = get<0>(txyl[kk]);
				int no_line = 0;
				for (int k = kk; k < txyl.size() && EQ(time,get<0>(txyl[k]));++k) {
					if (EQ(get<1>(txyl[k]),0) && EQ(get<2>(txyl[k]),0)) {
						++no_line;
					}
				}
				int max_group = 0;
				for (int l = kk; l < txyl.size() && EQ(time,get<0>(txyl[l])); ++l) {
					int num_group = 0;
					if (EQ(get<1>(txyl[l]),0) && EQ(get<2>(txyl[l]),0)) continue;
					for (int k = kk; k < txyl.size() && EQ(time,get<0>(txyl[k])); ++k) {
						if (EQ(get<1>(txyl[k]),0) && EQ(get<2>(txyl[k]),0)) continue;
						if (EQ(get<1>(txyl[l]) * get<2>(txyl[k]), get<1>(txyl[k]) * get<2>(txyl[l]))) {
							++num_group;
						}
					}
					max_group = max(max_group, num_group);
				}
				ccnt = max(ccnt, no_line + max_group);
				while (EQ(get<0>(txyl[kk]), time)) {
					++kk;
					if (kk == txyl.size()) break;
				}
			}
			//cout << "i:" << i << " j:" << j << " cnt:" << cnt << " ccnt:" << ccnt << " txyl:" << txyl.size() << endl;
			result = max(result, ccnt + cnt);
		}
	}
	if (flg == 0) {
		cout << n << endl;
	} else {
	cout << result << endl;
	}
	return 0;
}
accuracy: 0.23076923076923078
time_ms: 10
memory_kb: 3108
final_rank: 16

code_snippet: #define _USE_MATH_DEFINES
#include <iostream>
#include <queue>
#include <vector>
#include <math.h>
#include <algorithm>
#include <iomanip>
#include <string>
#include <stack>
#include <cctype>
#include <cstdlib>
#include <tuple>
using namespace std;

#define INF (1 << 20)
#define EPS (1e-10)
#define EQ(a,b) (fabs((a)-(b)) < EPS)

int main(){
	int x[200], y[200], u[200], v[200];
	int n;
	int result = 0;
	int flg = 0;
	cin >> n;
	if (n == 1 || n == 2) {
		cout << n << endl;
		return 0;
	}
	for (int i = 0; i < n; ++i) cin >> x[i] >> y[i] >> u[i] >> v[i];
	for (int i = 0; i < n; ++i) {
		for (int j = 0; j < n; ++j) {
			vector<tuple<double, double, double> > txyl;
			int cnt = 0;
			int xa = x[i] - x[j];
			int ya = y[i] - y[j];
			int ua = u[i] - u[j];
			int va = v[i] - v[j];
			if (xa == 0 && ya == 0) continue;
			flg = 1;
			for (int k = 0; k < n; ++k) {
				int xb = x[i] - x[k];
				int yb = y[i] - y[k];
				int ub = u[i] - u[k];
				int vb = v[i] - v[k];
				double a = ua * vb - ub * va;
				double b = xa * vb + ua * yb - xb * va - ub * ya;
				double c = xa * yb - xb * ya;
				if (a == 0 && b == 0) {
					if (c == 0)	++cnt;
				} else if (a == 0) {
					double t = -c/b;
					txyl.push_back(make_tuple(t, xb + t * ub, yb + t * vb));
				} else {
					if (b * b - 4 * a * c < 0) continue;
					double temp = sqrt(b * b - 4 * a * c);
					if (EQ(temp/a,0)) {
						double t = -b / 2.0 / a;
					txyl.push_back(make_tuple(t, xb + t * ub, yb + t * vb));
						continue;
					}
					double t = (-b + temp) / 2.0 / a;
					txyl.push_back(make_tuple(t, xb + t * ub, yb + t * vb));
					t = (-b - temp) / 2.0 / a;
					txyl.push_back(make_tuple(t, xb + t * ub, yb + t * vb));
				}
			}
			sort(txyl.begin(), txyl.end());
			int kk = 0;
			while (kk < txyl.size() && get<0>(txyl[kk]) < -EPS) ++kk;
			int ccnt = 0;
			while (kk < txyl.size()) {
				double time = get<0>(txyl[kk]);
				int no_line = 0;
				for (int k = kk; k < txyl.size() && EQ(time,get<0>(txyl[k]));++k) {
					if (EQ(get<1>(txyl[k]),0) && EQ(get<2>(txyl[k]),0)) {
						++no_line;
					}
				}
				int max_group = 0;
				for (int l = kk; l < txyl.size() && EQ(time,get<0>(txyl[l])); ++l) {
					int num_group = 0;
					if (EQ(get<1>(txyl[l]),0) && EQ(get<2>(txyl[l]),0)) continue;
					for (int k = kk; k < txyl.size() && EQ(time,get<0>(txyl[k])); ++k) {
						if (EQ(get<1>(txyl[k]),0) && EQ(get<2>(txyl[k]),0)) continue;
						if (EQ(get<1>(txyl[l]) * get<2>(txyl[k]), get<1>(txyl[k]) * get<2>(txyl[l]))) {
							++num_group;
						}
					}
					max_group = max(max_group, num_group);
				}
				ccnt = max(ccnt, no_line + max_group);
				while (EQ(get<0>(txyl[kk]), time)) {
					++kk;
					if (kk == txyl.size()) break;
				}
			}
			//cout << "i:" << i << " j:" << j << " cnt:" << cnt << " ccnt:" << ccnt << " txyl:" << txyl.size() << endl;
			result = max(result, ccnt + cnt);
		}
	}
	if (flg == 0) {
		cout << n << endl;
	} else {
	cout << result << endl;
	}
	return 0;
}
accuracy: 0.6410256410256411
time_ms: 610
memory_kb: 3128
final_rank: 10

code_snippet: #define _USE_MATH_DEFINES
#include <iostream>
#include <queue>
#include <vector>
#include <math.h>
#include <algorithm>
#include <iomanip>
#include <string>
#include <stack>
#include <cctype>
#include <cstdlib>
#include <tuple>
using namespace std;

#define INF (1 << 20)

int main(){
	int x[200], y[200], u[200], v[200];
	int n;
	int result = 0;
	int flg = 0;
	cin >> n;
	if (n == 1 || n == 2) {
		cout << n << endl;
		return 0;
	}
	for (int i = 0; i < n; ++i) cin >> x[i] >> y[i] >> u[i] >> v[i];
	for (int i = 0; i < n; ++i) {
		for (int j = 0; j < n; ++j) {
			vector<tuple<double, double, double> > txyl;
			int cnt = 0;
			int xa = x[i] - x[j];
			int ya = y[i] - y[j];
			int ua = u[i] - u[j];
			int va = v[i] - v[j];
			if (xa == 0 && ya == 0 && ua == 0 && va == 0) continue;
			flg = 1;
			for (int k = 0; k < n; ++k) {
				int xb = x[i] - x[k];
				int yb = y[i] - y[k];
				int ub = u[i] - u[k];
				int vb = v[i] - v[k];
				double a = ua * vb - ub * va;
				double b = xa * vb + ua * yb - xb * va - ub * ya;
				double c = xa * yb - xb * ya;
				if (fabs(a) <= 1e-10 && fabs(b) <= 1e-10) {
					if (c == 0)	++cnt;
					continue;
				} else if (fabs(a) <= 1e-10) {
					double t = -c/b;
					txyl.push_back(make_tuple(t, xb + t * ub, yb + t * vb));
				} else {
					if (b * b - 4 * a * c < 0) continue;
					double temp = sqrt(b * b - 4 * a * c);
					if (temp <= 1e-10) {
						double t = -b / 2.0 / a;
					txyl.push_back(make_tuple(t, xb + t * ub, yb + t * vb));
						continue;
					}
					double t = (-b + temp) / 2.0 / a;
					txyl.push_back(make_tuple(t, xb + t * ub, yb + t * vb));
					t = (-b - temp) / 2.0 / a;
					txyl.push_back(make_tuple(t, xb + t * ub, yb + t * vb));
				}
			}
			sort(txyl.begin(), txyl.end());
			int kk = 0;
			while (kk < txyl.size() && get<0>(txyl[kk]) < 0) ++kk;
			int ccnt = 0;
			while (kk < txyl.size()) {
				double time = get<0>(txyl[kk]);
				int no_line = 0;
				for (int k = kk; k < txyl.size() && time == get<0>(txyl[k]) ;++k) {
					if (fabs(get<1>(txyl[k])) <= 1e-10 && fabs(get<2>(txyl[k])) <= 1e-10) {
						++no_line;
					}
				}
				int max_group = 0;
				for (int l = kk; l < txyl.size() && time == get<0>(txyl[l]); ++l) {
					int num_group = 0;
					if (fabs(get<1>(txyl[l])) <= 1e-10 && fabs(get<2>(txyl[l])) <= 1e-10) continue;
					for (int k = kk; k < txyl.size() && time == get<0>(txyl[k]); ++k) {
						if (fabs(get<1>(txyl[k])) <= 1e-10 && fabs(get<2>(txyl[k])) <= 1e-10) continue;
						if (fabs(get<1>(txyl[l]) * get<2>(txyl[k]) - get<1>(txyl[k]) * get<2>(txyl[l])) <= 1e-10) {
							++num_group;
						}
					}
					max_group = max(max_group, num_group);
				}
				ccnt = max(ccnt, no_line + max_group);
				while (get<0>(txyl[kk]) == time) {
					++kk;
					if (kk == txyl.size()) break;
				}
			}
			//cout << "i:" << i << " j:" << j << " cnt:" << cnt << " ccnt:" << ccnt << " txyl:" << txyl.size() << endl;
			result = max(result, ccnt + cnt);
		}
	}
	if (flg == 0) {
		cout << n << endl;
	} else {
	cout << result << endl;
	}
	return 0;
}
accuracy: 0.6153846153846154
time_ms: 610
memory_kb: 3116
final_rank: 11

code_snippet: #define _USE_MATH_DEFINES
#include <iostream>
#include <queue>
#include <vector>
#include <math.h>
#include <algorithm>
#include <iomanip>
#include <string>
#include <stack>
#include <cctype>
#include <cstdlib>
using namespace std;

#define INF (1 << 20)
int main(){
	int x[200], y[200], u[200], v[200];
	int n;
	int result = 0;
	int flg = 0;
	cin >> n;
	if (n == 1 || n == 2) {
		cout << n << endl;
		return 0;
	}
	for (int i = 0; i < n; ++i) cin >> x[i] >> y[i] >> u[i] >> v[i];
	for (int i = 0; i < n; ++i) {
		for (int j = 0; j < n; ++j) {
			if (i == j) continue;
			vector<double> tl;
			vector<double> xl;
			vector<double> yl;
			int cnt = 0;
			int xa = x[i] - x[j];
			int ya = y[i] - y[j];
			int ua = u[i] - u[j];
			int va = v[i] - v[j];
			if (xa == 0 && ya == 0 && ua == 0 && va == 0) continue;
			flg = 1;
			for (int k = 0; k < n; ++k) {
				int xb = x[i] - x[k];
				int yb = y[i] - y[k];
				int ub = u[i] - u[k];
				int vb = v[i] - v[k];
				double a = ua * vb - ub * va;
				double b = xa * vb + ua * yb - xb * va - ub * ya;
				double c = xa * yb - xb * ya;
				if (a == 0 && b == 0) {
					if (c == 0) ++cnt;
					continue;
				} else if (a == 0 && b != 0) {
					double t = -c/b;
					tl.push_back(t);
					xl.push_back(xb + t * ub);
					yl.push_back(yb + t * vb);
				} else if (a != 0) {
					if (b * b - 4 * a * c < 0) continue;
					double temp = sqrt(b * b - 4 * a * c);
					if (b * b - 4 * a * c == 0) {
						double t = -b/2/a;
						tl.push_back(t);
						xl.push_back(xb + t * ub);
						yl.push_back(yb + t * vb);
						continue;
					}
					double t = (-b + temp) / 2 / a;
					tl.push_back(t);
					xl.push_back(xb + t * ub);
					yl.push_back(yb + t * vb);
					t = (-b - temp) / 2 / a;
					tl.push_back(t);
					xl.push_back(xb + t * ub);
					yl.push_back(yb + t * vb);
				}
			}
			int ccnt = 0;
			int flgs[1000] = {};
			for (int k = 0; k < tl.size(); ++k) {
				if (tl[k] < 0) continue;
				int cccnt = 0;
				if (xl[k] == 0 && yl[k] == 0) {
					if (flgs[k] == 0) flgs[k] = 1;
					continue;
				}
				for (int l = 0; l < tl.size(); ++l) {
					if (tl[l] < 0) continue;
					if (fabs(tl[k] - tl[l]) <= 1e-10 && xl[k] * yl[l] == xl[l] * yl[k]) {
						++cccnt;
						flgs[k] = -1;
					}
				}
				ccnt = max(ccnt, cccnt);
			}
			for (int k = 0; k < tl.size(); ++k) {
				if (flgs[k] == 1) {
					int asdf = 0;
					for (int l = 0; l < tl.size(); ++l) {
						if (fabs(tl[k] - tl[l]) <= 1e-10) ++asdf;
					}
					ccnt = max(ccnt, asdf);
				}
			}
			result = max(result, ccnt + cnt);
		}
	}
	if (flg == 0) {
		cout << n << endl;
	} else {
	cout << result << endl;
	}
	return 0;
}
accuracy: 0.358974358974359
time_ms: 550
memory_kb: 1232
final_rank: 14