Problem:
Problem I
Midpoint
One day, you found $L + M + N$ points on a 2D plane, which you named $A_1, ..., A_L, B_1, ...,B_M, C_1,...,C_N$. Note that two or more points of them can be at the same coordinate. These were named after the following properties:
the points $A_1,...,A_L$ were located on a single straight line,
the points $B_1,...,B_M$ were located on a single straight line, and
the points $C_1,...,C_N$ were located on a single straight line.
Now, you are interested in a triplet $(i, j, k)$ such that $C_k$ is the midpoint between $A_i$ and $B_j$. Your task is counting such triplets.
Input
The first line contains three space-separated positive integers $L$, $M$, and $N$ $(1 \leq L, M, N \leq 10^5)$. The next $L$ lines describe $A$. The $i$-th of them contains two space-separated integers representing the $x$-coordinate and the $y$-coordinate of $A_i$. The next $M$ lines describe $B$. The $j$-th of them contains two space-separated integers representing the $x$-coordinate and the $y$-coordinate of $B_j$. The next $N$ lines describe $C$. The $k$-th of them contains two space-separated integers representing the $x$-coordinate and the $y$-coordinate of $C_k$. It is guaranteed that the absolute values of all the coordinates do not exceed $10^5$.
Output
Print the number of the triplets which fulfill the constraint.
Sample Input 1
2 2 3
0 0
2 0
0 0
0 2
0 0
1 1
1 1
Output for the Sample Input 1
3
Sample Input 2
4 4 4
3 5
0 4
6 6
9 7
8 2
11 3
2 0
5 1
4 3
7 4
10 5
1 2
Output for the Sample Input 2
8
Sample Input 3
4 4 4
0 0
3 2
6 4
9 6
7 14
9 10
10 8
13 2
4 2
5 4
6 6
8 10
Output for the Sample Input 3
3

Submitted solutions:

code_snippet: #include<bits/stdc++.h>
using namespace std;
#define ll long long
#define nn 65536*8
struct point{
	ll x,y;
	point (ll xx=0,ll yy=0){
		x=xx,y=yy;
	}
};
point operator-(point a,point b){
	return point(a.x-b.x,a.y-b.y);
}
point operator+(point a,point b){
	return point(a.x+b.x,a.y+b.y);
}
point operator*(point a,ll b){
	return point(a.x*b,a.y*b);
}
int operator==(point a,point b){
	return (a.x==b.x and a.y==b.y);
}


bool operator<(point a,point b){
	if(a.x!=b.x) return a.x<b.x;
	return a.y<b.y;
}

int bf=0;
point getin(int n,point pn[],ll has[]){
	for(int i=1;i<=n;i++) scanf("%lld%lld",&pn[i].x,&pn[i].y);
	sort(pn+1,pn+n+1);
	point p=pn[n]-pn[1];if(pn[n]==pn[1]){
		bf=1;
		return p;
	}
	int d=__gcd(p.x,p.y);
	if(d) p.x/=d,p.y/=d;
	if(p.x<0) p.x*=-1,p.y*=-1;
	
	for(int i=1;i<=n;i++){
		point dif=pn[i]-pn[1];
		if(p.x==0) {
			if(dif.y/p.y>=0)
			has[dif.y/p.y]++;
		}
		else 
		{
			if(dif.x/p.x>=0)
			has[dif.x/p.x]++;
		}
	}
	return p;
}
int l,n,m;point pl[nn],pn[nn],pm[nn];
point vl,vn,vm;ll hasl[nn],hasn[nn],hasm[nn];

ll ans=0;
	map<point,int> ump;
namespace pack1{
	#define mod 998244353
	ll qpow(ll x,ll y){
		while(y<0) y+=mod-1;
		ll res=1;
		while(y){
			if(y&1) res=res*x%mod;
			x=x*x%mod;y=y/2;
		}
		return res;
	}
	int pos[nn];
	void getpos(){
		for(int i=0;i<nn;i++)
			pos[i]=(pos[i>>1]>>1)|((i&1)<<16+3-1);
	}
	void ntt(ll a[],ll ctrl){
		for(int i=0;i<nn;i++) if(pos[i]>i) swap(a[pos[i]],a[i]);
		for(int p=1;p<nn;p<<=1){
			int m=p+p;ll w=qpow(3,(mod-1)*ctrl/m);
			for(int i=0;i<nn;i+=m){
				for(ll wx=1,j=i;j<i+p;j++,wx=wx*w%mod){
					ll e=a[j],f=a[j+p]*wx%mod;
					a[j]=(e+f)%mod,a[j+p]=(e-f)%mod;
				}
			}
		}
		
		ll div=qpow(nn,mod-2);
		if(ctrl==-1) for(int i=0;i<nn;i++) a[i]=a[i]*div%mod;
	}
	
	void solve(){
		getpos();
		ntt(hasl,1);ntt(hasn,1);
		for(int i=0;i<nn;i++) hasn[i]=hasn[i]*hasl[i]%mod;
		ntt(hasn,-1);
		
		for(int i=1;i<=m;i++) ump[pm[i]*2]++;
		
		for(int i=0;i<nn;i++) {
			point o=pn[1]+pl[1]+(vl*i);
			ans+=ump[o]*((hasn[i]+mod)%mod);
		}
		
	}
	#undef mod 
};
#define lf double
namespace pack2{
	ll solve(lf a,lf b,lf c,lf d,lf e,lf f){
		lf x=0,y=0;
		if(fabs(a)<1e-9){
			y=c/b;
		}
		else{
			f-=d/a*c,e-=d/a*b;
			d-=d/a*a;
			y=f/e;
		}
		return y;
	}
	void solve(){
		for(int i=1;i<=l;i++){
			ump[pl[i]]++;
		}
		for(int i=1;i<=m;i++){
			point o=pm[i]*2-pl[1]-pn[1];
			ll sol=solve(vl.x,vn.x,o.x,vl.y,vn.y,o.y);
			if(sol<0 or sol>=nn) continue;
			point ask=pm[i]*2-(pn[1]+vn*sol);
			ans+=ump[ask]*hasn[sol];
			sol--;
			
			ask=pm[i]*2-(pn[1]+vn*sol);
			if(sol>=0)ans+=ump[ask]*hasn[sol];
			
			sol++;sol++;
			ask=pm[i]*2-(pn[1]+vn*sol);
			ans+=ump[ask]*hasn[sol];
		}
	}
};
namespace pack3{
	map<point,ll> ml,mn,mm;
	void solve(){
		for(int i=1;i<=l;i++) ml[pl[i]]++;
		for(int i=1;i<=n;i++) mn[pn[i]]++;
		for(int i=1;i<=m;i++) mm[pm[i]*2]++;
		if(mm.size()>1){
			assert(1ll*mn.size()*ml.size()<=1e6);
			for(map<point,ll>::iterator x=ml.begin();x!=ml.end();x++){
				for(map<point,ll>::iterator y=mn.begin();y!=mn.end();y++){
					ans+=x->second*y->second*mm[y->first+x->first];	
				}
			}
		}	
		else {
			if(ml.size()>1) swap(mn,ml);
			assert(1ll*ml.size()*mm.size()<=1e6);
			for(map<point,ll>::iterator x=ml.begin();x!=ml.end();x++){
				for(map<point,ll>::iterator y=mm.begin();y!=mm.end();y++){
					ans+=x->second*y->second*mn[y->first-x->first];	
				}
			}
		}
	} 
}
int main(){
	scanf("%d%d%d",&l,&n,&m);
	vl=getin(l,pl,hasl);vn=getin(n,pn,hasn);vm=getin(m,pm,hasm);
	if(bf)
		pack3::solve();
	else if(vl==vn)
		pack1::solve();
	else 
		pack2::solve();
	
	printf("%lld\n",ans);
	
	
	return 0;
}
accuracy: 1
time_ms: 270
memory_kb: 79436
final_rank: 5

code_snippet: // AOJ #2695 Midpoint
// 2025.3.23

#include <bits/stdc++.h>
using namespace std;
using ll = long long;

#define gc() getchar_unlocked()
#define pc(c) putchar_unlocked(c)

int Cin() {
	int n = 0; int c = gc();
	if (c == '-') {	c = gc();
		do n = 10*n + (c & 0xf), c = gc(); while (c >= '0');
		return -n;
	}
	do n = 10*n + (c & 0xf), c = gc(); while (c >= '0');
	return n;
}

void Cout(ll n) {
	char b[30];
	if (!n) pc('0');
	else {
		if (n < 0) pc('-'), n = -n;
		int i = 0; while (n) b[i++] = n % 10 + '0', n /= 10;
		while (i--) pc(b[i]);
	}
	pc('\n');
}

const double PI = acos(-1.0);

struct cmp {
    double x, y;
    cmp operator+(const cmp &u) const { return {x + u.x, y + u.y}; }
    cmp operator-(const cmp &u) const { return {x - u.x, y - u.y}; }
    cmp operator*(const cmp &u) const { return {x * u.x - y * u.y, x * u.y + y * u.x}; }
    cmp operator/(double u) const { return {x / u, y / u}; }
};

cmp FT_A[800010], FT_B[800010];
int REV[800010];

void getRev(int l, int cnt) {
    for (int i = 1; i < l; i++)
        REV[i] = (REV[i >> 1] >> 1) | ((i & 1) << (cnt - 1));
}

void fft(cmp t[], int l, int f) {
    for (int i = 0; i < l; i++) {
        if (i < REV[i]) swap(t[i], t[REV[i]]);
    }
    for (int d = 2; d <= l; d <<= 1) {
        cmp w0 = { cos(2.0 * PI / d), -f * sin(2.0 * PI / d) };
        for (int i = 0; i < l; i += d) {
            cmp cur = { 1.0, 0.0 };
            for (int j = 0; j < d / 2; j++, cur = cur * w0) {
                cmp ta = t[i + j], tb = t[i + j + d / 2] * cur;
                t[i + j] = ta + tb;
                t[i + j + d / 2] = ta - tb;
            }
        }
    }
    if (f == -1) for (int i = 0; i < l; i++) t[i] = t[i] / (double)l;
}

pair<int,int> a[100010], b[100010], c[100010];
ll ans, val[100010];
map<pair<int,int>, int> mpNum;
map<ll, int> mpIdA, mpIdB;
vector<pair<int,int> > totA[100010], totB[100010];
int cntA, cntB;
int la, lb, lc;

vector<ll> mult(const vector<int> &F, const vector<int> &G) {
    int n = 1; while(n < (int)F.size() + (int)G.size()) n <<= 1;
    vector<cmp> P(n), Q(n);
    for (int i = 0; i < (int)F.size(); i++) P[i] = { (double)F[i], 0.0 };
    for (int i = 0; i < (int)G.size(); i++) Q[i] = { (double)G[i], 0.0 };
    fft(&P[0], n, 1); fft(&Q[0], n, 1);
    for (int i = 0; i < n; i++) P[i] = P[i] * Q[i];
    fft(&P[0], n, -1);
    vector<ll> R(F.size() + G.size() - 1);
    for (int i = 0; i < (int)R.size(); i++) R[i] = (ll)(P[i].x + 0.5);
    return R;
}

int main(){
    la = Cin(), lb = Cin(), lc = Cin();
    for (int i = 1; i <= la; i++) a[i].first = Cin(), a[i].second = Cin();
    for (int i = 1; i <= lb; i++) b[i].first = Cin(), b[i].second = Cin();
    for (int i = 1; i <= lc; i++) c[i].first = Cin(), c[i].second = Cin();

    sort(a + 1, a + la + 1);
    sort(b + 1, b + lb + 1);
    sort(c + 1, c + lc + 1);
    if(c[1] == c[lc]) {
        for (int i = 1; i <= la; i++) mpNum[a[i]]++;
        for (int i = 1; i <= lb; i++) {
            pair<int,int> tmp = { c[1].first * 2 - b[i].first, c[1].second * 2 - b[i].second };
            ans += mpNum[tmp];
        }
        ans *= lc;
        Cout(ans);
        return 0;
    }
    for (int i = 1; i <= lc; i++) mpNum[{ c[i].first * 2, c[i].second * 2 }]++;
    for (int i = 1; i <= la; i++) {
        ll v = 1LL * (c[1].first - a[i].first) * (c[lc].second - a[i].second)
                    - 1LL * (c[1].second - a[i].second) * (c[lc].first - a[i].first);
        if(mpIdA.find(v) == mpIdA.end()) {
            mpIdA[v] = ++cntA;
            val[cntA] = v;
        }
        totA[ mpIdA[v] ].push_back(a[i]);
    }
    for (int i = 1; i <= lb; i++) {
        ll v = 1LL * (c[1].first - b[i].first) * (c[lc].second - b[i].second)
                    - 1LL * (c[1].second - b[i].second) * (c[lc].first - b[i].first);
        if(mpIdB.find(v) == mpIdB.end()) mpIdB[v] = ++cntB;
        totB[ mpIdB[v] ].push_back(b[i]);
    }
    int L = 1, cnt = 0;
    while(L < 400001) { L <<= 1; cnt++; }
    getRev(L, cnt);
    for (int i = 1; i <= cntA; i++) {
        int t = mpIdB[-val[i]];
        if (!t) continue;
        int s1 = totA[i].size(), s2 = totB[t].size();
        if(totA[i][0] == totA[i][s1 - 1]) {
            for (int j = 0; j < s2; j++)
                ans += 1LL * s1 * mpNum[{ totA[i][0].first + totB[t][j].first,
                                           totA[i][0].second + totB[t][j].second }];
        }
        else if(totB[t][0] == totB[t][s2 - 1]) {
            for (int j = 0; j < s1; j++)
                ans += 1LL * s2 * mpNum[{ totA[i][j].first + totB[t][0].first,
                                           totA[i][j].second + totB[t][0].second }];
        }
        else {
            for (int j = 0; j < s1; j++) {
                if(c[1].first != c[lc].first)
                    FT_A[ totA[i][j].first + 100000 ].x += 1.0;
                else
                    FT_A[ totA[i][j].second + 100000 ].x += 1.0;
            }
            for (int j = 0; j < s2; j++) {
                if(c[1].first != c[lc].first)
                    FT_B[ totB[t][j].first + 100000 ].x += 1.0;
                else
                    FT_B[ totB[t][j].second + 100000 ].x += 1.0;
            }
            fft(FT_A, L, 1);
            fft(FT_B, L, 1);
            for (int j = 0; j < L; j++) FT_A[j] = FT_A[j] * FT_B[j];
            fft(FT_A, L, -1);
            for (int j = 1; j <= lc; j++) {
                if(c[1].first != c[lc].first) ans += (ll)(FT_A[c[j].first * 2 + 200000].x + 0.5);
                else                         ans += (ll)(FT_A[c[j].second * 2 + 200000].x + 0.5);
            }
        }
    }
    Cout(ans);
    return 0;
}
accuracy: 1
time_ms: 150
memory_kb: 41760
final_rank: 1

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,INF=1<<30;

//modint+畳み込み+逆元テーブル

// from: https://gist.github.com/yosupo06/ddd51afb727600fd95d9d8ad6c3c80c9
// (based on AtCoder STL)

#include <algorithm>
#include <array>

#ifdef _MSC_VER
#include <intrin.h>
#endif

namespace atcoder {
    
    namespace internal {
        
        int ceil_pow2(int n) {
            int x = 0;
            while ((1U << x) < (unsigned int)(n)) x++;
            return x;
        }
        
        int bsf(unsigned int n) {
#ifdef _MSC_VER
            unsigned long index;
            _BitScanForward(&index, n);
            return index;
#else
            return __builtin_ctz(n);
#endif
        }
        
    }  // namespace internal
    
}  // namespace atcoder



#include <utility>

namespace atcoder {
    
    namespace internal {
        
        constexpr long long safe_mod(long long x, long long m) {
            x %= m;
            if (x < 0) x += m;
            return x;
        }
        
        struct barrett {
            unsigned int _m;
            unsigned long long im;
            
            barrett(unsigned int m) : _m(m), im((unsigned long long)(-1) / m + 1) {}
            
            unsigned int umod() const { return _m; }
            
            unsigned int mul(unsigned int a, unsigned int b) const {
                
                unsigned long long z = a;
                z *= b;
#ifdef _MSC_VER
                unsigned long long x;
                _umul128(z, im, &x);
#else
                unsigned long long x =
                (unsigned long long)(((unsigned __int128)(z)*im) >> 64);
#endif
                unsigned int v = (unsigned int)(z - x * _m);
                if (_m <= v) v += _m;
                return v;
            }
        };
        
        constexpr long long pow_mod_constexpr(long long x, long long n, int m) {
            if (m == 1) return 0;
            unsigned int _m = (unsigned int)(m);
            unsigned long long r = 1;
            unsigned long long y = safe_mod(x, m);
            while (n) {
                if (n & 1) r = (r * y) % _m;
                y = (y * y) % _m;
                n >>= 1;
            }
            return r;
        }
        
        constexpr bool is_prime_constexpr(int n) {
            if (n <= 1) return false;
            if (n == 2 || n == 7 || n == 61) return true;
            if (n % 2 == 0) return false;
            long long d = n - 1;
            while (d % 2 == 0) d /= 2;
            for (long long a : {2, 7, 61}) {
                long long t = d;
                long long y = pow_mod_constexpr(a, t, n);
                while (t != n - 1 && y != 1 && y != n - 1) {
                    y = y * y % n;
                    t <<= 1;
                }
                if (y != n - 1 && t % 2 == 0) {
                    return false;
                }
            }
            return true;
        }
        template <int n> constexpr bool is_prime = is_prime_constexpr(n);
        
        constexpr std::pair<long long, long long> inv_gcd(long long a, long long b) {
            a = safe_mod(a, b);
            if (a == 0) return {b, 0};
            
            long long s = b, t = a;
            long long m0 = 0, m1 = 1;
            
            while (t) {
                long long u = s / t;
                s -= t * u;
                m0 -= m1 * u;  // |m1 * u| <= |m1| * s <= b
                
                
                auto tmp = s;
                s = t;
                t = tmp;
                tmp = m0;
                m0 = m1;
                m1 = tmp;
            }
            if (m0 < 0) m0 += b / s;
            return {s, m0};
        }
        
        constexpr int primitive_root_constexpr(int m) {
            if (m == 2) return 1;
            if (m == 167772161) return 3;
            if (m == 469762049) return 3;
            if (m == 754974721) return 11;
            if (m == 998244353) return 3;
            int divs[20] = {};
            divs[0] = 2;
            int cnt = 1;
            int x = (m - 1) / 2;
            while (x % 2 == 0) x /= 2;
            for (int i = 3; (long long)(i)*i <= x; i += 2) {
                if (x % i == 0) {
                    divs[cnt++] = i;
                    while (x % i == 0) {
                        x /= i;
                    }
                }
            }
            if (x > 1) {
                divs[cnt++] = x;
            }
            for (int g = 2;; g++) {
                bool ok = true;
                for (int i = 0; i < cnt; i++) {
                    if (pow_mod_constexpr(g, (m - 1) / divs[i], m) == 1) {
                        ok = false;
                        break;
                    }
                }
                if (ok) return g;
            }
        }
        template <int m> constexpr int primitive_root = primitive_root_constexpr(m);
        
    }  // namespace internal
    
}  // namespace atcoder


#include <cassert>
#include <numeric>
#include <type_traits>

namespace atcoder {
    
    namespace internal {
        
#ifndef _MSC_VER
        template <class T>
        using is_signed_int128 =
        typename std::conditional<std::is_same<T, __int128_t>::value ||
        std::is_same<T, __int128>::value,
        std::true_type,
        std::false_type>::type;
        
        template <class T>
        using is_unsigned_int128 =
        typename std::conditional<std::is_same<T, __uint128_t>::value ||
        std::is_same<T, unsigned __int128>::value,
        std::true_type,
        std::false_type>::type;
        
        template <class T>
        using make_unsigned_int128 =
        typename std::conditional<std::is_same<T, __int128_t>::value,
        __uint128_t,
        unsigned __int128>;
        
        template <class T>
        using is_integral = typename std::conditional<std::is_integral<T>::value ||
        is_signed_int128<T>::value ||
        is_unsigned_int128<T>::value,
        std::true_type,
        std::false_type>::type;
        
        template <class T>
        using is_signed_int = typename std::conditional<(is_integral<T>::value &&
                                                         std::is_signed<T>::value) ||
        is_signed_int128<T>::value,
        std::true_type,
        std::false_type>::type;
        
        template <class T>
        using is_unsigned_int =
        typename std::conditional<(is_integral<T>::value &&
                                   std::is_unsigned<T>::value) ||
        is_unsigned_int128<T>::value,
        std::true_type,
        std::false_type>::type;
        
        template <class T>
        using to_unsigned = typename std::conditional<
        is_signed_int128<T>::value,
        make_unsigned_int128<T>,
        typename std::conditional<std::is_signed<T>::value,
        std::make_unsigned<T>,
        std::common_type<T>>::type>::type;
        
#else
        
        template <class T> using is_integral = typename std::is_integral<T>;
        
        template <class T>
        using is_signed_int =
        typename std::conditional<is_integral<T>::value && std::is_signed<T>::value,
        std::true_type,
        std::false_type>::type;
        
        template <class T>
        using is_unsigned_int =
        typename std::conditional<is_integral<T>::value &&
        std::is_unsigned<T>::value,
        std::true_type,
        std::false_type>::type;
        
        template <class T>
        using to_unsigned = typename std::conditional<is_signed_int<T>::value,
        std::make_unsigned<T>,
        std::common_type<T>>::type;
        
#endif
        
        template <class T>
        using is_signed_int_t = std::enable_if_t<is_signed_int<T>::value>;
        
        template <class T>
        using is_unsigned_int_t = std::enable_if_t<is_unsigned_int<T>::value>;
        
        template <class T> using to_unsigned_t = typename to_unsigned<T>::type;
        
    }  // namespace internal
    
}  // namespace atcoder

#include <cassert>
#include <numeric>
#include <type_traits>

#ifdef _MSC_VER
#include <intrin.h>
#endif

namespace atcoder {
    
    namespace internal {
        
        struct modint_base {};
        struct static_modint_base : modint_base {};
        
        template <class T> using is_modint = std::is_base_of<modint_base, T>;
        template <class T> using is_modint_t = std::enable_if_t<is_modint<T>::value>;
        
    }  // namespace internal
    
    template <int m, std::enable_if_t<(1 <= m)>* = nullptr>
    struct static_modint : internal::static_modint_base {
        using mint = static_modint;
        
    public:
        static constexpr int mod() { return m; }
        static mint raw(int v) {
            mint x;
            x._v = v;
            return x;
        }
        
        static_modint() : _v(0) {}
        template <class T, internal::is_signed_int_t<T>* = nullptr>
        static_modint(T v) {
            long long x = (long long)(v % (long long)(umod()));
            if (x < 0) x += umod();
            _v = (unsigned int)(x);
        }
        template <class T, internal::is_unsigned_int_t<T>* = nullptr>
        static_modint(T v) {
            _v = (unsigned int)(v % umod());
        }
        static_modint(bool v) { _v = ((unsigned int)(v) % umod()); }
        
        unsigned int val() const { return _v; }
        
        mint& operator++() {
            _v++;
            if (_v == umod()) _v = 0;
            return *this;
        }
        mint& operator--() {
            if (_v == 0) _v = umod();
            _v--;
            return *this;
        }
        mint operator++(int) {
            mint result = *this;
            ++*this;
            return result;
        }
        mint operator--(int) {
            mint result = *this;
            --*this;
            return result;
        }
        
        mint& operator+=(const mint& rhs) {
            _v += rhs._v;
            if (_v >= umod()) _v -= umod();
            return *this;
        }
        mint& operator-=(const mint& rhs) {
            _v -= rhs._v;
            if (_v >= umod()) _v += umod();
            return *this;
        }
        mint& operator*=(const mint& rhs) {
            unsigned long long z = _v;
            z *= rhs._v;
            _v = (unsigned int)(z % umod());
            return *this;
        }
        mint& operator/=(const mint& rhs) { return *this = *this * rhs.inv(); }
        
        mint operator+() const { return *this; }
        mint operator-() const { return mint() - *this; }
        
        mint pow(long long n) const {
            assert(0 <= n);
            mint x = *this, r = 1;
            while (n) {
                if (n & 1) r *= x;
                x *= x;
                n >>= 1;
            }
            return r;
        }
        mint inv() const {
            if (prime) {
                assert(_v);
                return pow(umod() - 2);
            } else {
                auto eg = internal::inv_gcd(_v, m);
                assert(eg.first == 1);
                return eg.second;
            }
        }
        
        friend mint operator+(const mint& lhs, const mint& rhs) {
            return mint(lhs) += rhs;
        }
        friend mint operator-(const mint& lhs, const mint& rhs) {
            return mint(lhs) -= rhs;
        }
        friend mint operator*(const mint& lhs, const mint& rhs) {
            return mint(lhs) *= rhs;
        }
        friend mint operator/(const mint& lhs, const mint& rhs) {
            return mint(lhs) /= rhs;
        }
        friend bool operator==(const mint& lhs, const mint& rhs) {
            return lhs._v == rhs._v;
        }
        friend bool operator!=(const mint& lhs, const mint& rhs) {
            return lhs._v != rhs._v;
        }
        
    private:
        unsigned int _v;
        static constexpr unsigned int umod() { return m; }
        static constexpr bool prime = internal::is_prime<m>;
    };
    
    template <int id> struct dynamic_modint : internal::modint_base {
        using mint = dynamic_modint;
        
    public:
        static int mod() { return (int)(bt.umod()); }
        static void set_mod(int m) {
            assert(1 <= m);
            bt = internal::barrett(m);
        }
        static mint raw(int v) {
            mint x;
            x._v = v;
            return x;
        }
        
        dynamic_modint() : _v(0) {}
        template <class T, internal::is_signed_int_t<T>* = nullptr>
        dynamic_modint(T v) {
            long long x = (long long)(v % (long long)(mod()));
            if (x < 0) x += mod();
            _v = (unsigned int)(x);
        }
        template <class T, internal::is_unsigned_int_t<T>* = nullptr>
        dynamic_modint(T v) {
            _v = (unsigned int)(v % mod());
        }
        dynamic_modint(bool v) { _v = ((unsigned int)(v) % mod()); }
        
        unsigned int val() const { return _v; }
        
        mint& operator++() {
            _v++;
            if (_v == umod()) _v = 0;
            return *this;
        }
        mint& operator--() {
            if (_v == 0) _v = umod();
            _v--;
            return *this;
        }
        mint operator++(int) {
            mint result = *this;
            ++*this;
            return result;
        }
        mint operator--(int) {
            mint result = *this;
            --*this;
            return result;
        }
        
        mint& operator+=(const mint& rhs) {
            _v += rhs._v;
            if (_v >= umod()) _v -= umod();
            return *this;
        }
        mint& operator-=(const mint& rhs) {
            _v += mod() - rhs._v;
            if (_v >= umod()) _v -= umod();
            return *this;
        }
        mint& operator*=(const mint& rhs) {
            _v = bt.mul(_v, rhs._v);
            return *this;
        }
        mint& operator/=(const mint& rhs) { return *this = *this * rhs.inv(); }
        
        mint operator+() const { return *this; }
        mint operator-() const { return mint() - *this; }
        
        mint pow(long long n) const {
            assert(0 <= n);
            mint x = *this, r = 1;
            while (n) {
                if (n & 1) r *= x;
                x *= x;
                n >>= 1;
            }
            return r;
        }
        mint inv() const {
            auto eg = internal::inv_gcd(_v, mod());
            assert(eg.first == 1);
            return eg.second;
        }
        
        friend mint operator+(const mint& lhs, const mint& rhs) {
            return mint(lhs) += rhs;
        }
        friend mint operator-(const mint& lhs, const mint& rhs) {
            return mint(lhs) -= rhs;
        }
        friend mint operator*(const mint& lhs, const mint& rhs) {
            return mint(lhs) *= rhs;
        }
        friend mint operator/(const mint& lhs, const mint& rhs) {
            return mint(lhs) /= rhs;
        }
        friend bool operator==(const mint& lhs, const mint& rhs) {
            return lhs._v == rhs._v;
        }
        friend bool operator!=(const mint& lhs, const mint& rhs) {
            return lhs._v != rhs._v;
        }
        
    private:
        unsigned int _v;
        static internal::barrett bt;
        static unsigned int umod() { return bt.umod(); }
    };
    template <int id> internal::barrett dynamic_modint<id>::bt = 998244353;
    
    using modint998244353 = static_modint<998244353>;
    using modint1000000007 = static_modint<1000000007>;
    using modint = dynamic_modint<-1>;
    
    namespace internal {
        
        template <class T>
        using is_static_modint = std::is_base_of<internal::static_modint_base, T>;
        
        template <class T>
        using is_static_modint_t = std::enable_if_t<is_static_modint<T>::value>;
        
        template <class> struct is_dynamic_modint : public std::false_type {};
        template <int id>
        struct is_dynamic_modint<dynamic_modint<id>> : public std::true_type {};
        
        template <class T>
        using is_dynamic_modint_t = std::enable_if_t<is_dynamic_modint<T>::value>;
        
    }  // namespace internal
    
}  // namespace atcoder

#include <cassert>
#include <type_traits>
#include <vector>

namespace atcoder {
    
    namespace internal {
        
        template <class mint, internal::is_static_modint_t<mint>* = nullptr>
        void butterfly(std::vector<mint>& a) {
            static constexpr int g = internal::primitive_root<mint::mod()>;
            int n = int(a.size());
            int h = internal::ceil_pow2(n);
            
            static bool first = true;
            static mint sum_e[30];  // sum_e[i] = ies[0] * ... * ies[i - 1] * es[i]
            if (first) {
                first = false;
                mint es[30], ies[30];  // es[i]^(2^(2+i)) == 1
                int cnt2 = bsf(mint::mod() - 1);
                mint e = mint(g).pow((mint::mod() - 1) >> cnt2), ie = e.inv();
                for (int i = cnt2; i >= 2; i--) {
                    es[i - 2] = e;
                    ies[i - 2] = ie;
                    e *= e;
                    ie *= ie;
                }
                mint now = 1;
                for (int i = 0; i < cnt2 - 2; i++) {
                    sum_e[i] = es[i] * now;
                    now *= ies[i];
                }
            }
            for (int ph = 1; ph <= h; ph++) {
                int w = 1 << (ph - 1), p = 1 << (h - ph);
                mint now = 1;
                for (int s = 0; s < w; s++) {
                    int offset = s << (h - ph + 1);
                    for (int i = 0; i < p; i++) {
                        auto l = a[i + offset];
                        auto r = a[i + offset + p] * now;
                        a[i + offset] = l + r;
                        a[i + offset + p] = l - r;
                    }
                    now *= sum_e[bsf(~(unsigned int)(s))];
                }
            }
        }
        
        template <class mint, internal::is_static_modint_t<mint>* = nullptr>
        void butterfly_inv(std::vector<mint>& a) {
            static constexpr int g = internal::primitive_root<mint::mod()>;
            int n = int(a.size());
            int h = internal::ceil_pow2(n);
            
            static bool first = true;
            static mint sum_ie[30];  // sum_ie[i] = es[0] * ... * es[i - 1] * ies[i]
            if (first) {
                first = false;
                mint es[30], ies[30];  // es[i]^(2^(2+i)) == 1
                int cnt2 = bsf(mint::mod() - 1);
                mint e = mint(g).pow((mint::mod() - 1) >> cnt2), ie = e.inv();
                for (int i = cnt2; i >= 2; i--) {
                    es[i - 2] = e;
                    ies[i - 2] = ie;
                    e *= e;
                    ie *= ie;
                }
                mint now = 1;
                for (int i = 0; i < cnt2 - 2; i++) {
                    sum_ie[i] = ies[i] * now;
                    now *= es[i];
                }
            }
            
            for (int ph = h; ph >= 1; ph--) {
                int w = 1 << (ph - 1), p = 1 << (h - ph);
                mint inow = 1;
                for (int s = 0; s < w; s++) {
                    int offset = s << (h - ph + 1);
                    for (int i = 0; i < p; i++) {
                        auto l = a[i + offset];
                        auto r = a[i + offset + p];
                        a[i + offset] = l + r;
                        a[i + offset + p] =
                        (unsigned long long)(mint::mod() + l.val() - r.val()) *
                        inow.val();
                    }
                    inow *= sum_ie[bsf(~(unsigned int)(s))];
                }
            }
        }
        
    }  // namespace internal
    
    template <class mint, internal::is_static_modint_t<mint>* = nullptr>
    std::vector<mint> convolution(std::vector<mint> a, std::vector<mint> b) {
        int n = int(a.size()), m = int(b.size());
        if (!n || !m) return {};
        if (std::min(n, m) <= 60) {
            if (n < m) {
                std::swap(n, m);
                std::swap(a, b);
            }
            std::vector<mint> ans(n + m - 1);
            for (int i = 0; i < n; i++) {
                for (int j = 0; j < m; j++) {
                    ans[i + j] += a[i] * b[j];
                }
            }
            return ans;
        }
        int z = 1 << internal::ceil_pow2(n + m - 1);
        a.resize(z);
        internal::butterfly(a);
        b.resize(z);
        internal::butterfly(b);
        for (int i = 0; i < z; i++) {
            a[i] *= b[i];
        }
        internal::butterfly_inv(a);
        a.resize(n + m - 1);
        mint iz = mint(z).inv();
        for (int i = 0; i < n + m - 1; i++) a[i] *= iz;
        return a;
    }
    
    template <unsigned int mod = 998244353,
    class T,
    std::enable_if_t<internal::is_integral<T>::value>* = nullptr>
    std::vector<T> convolution(const std::vector<T>& a, const std::vector<T>& b) {
        int n = int(a.size()), m = int(b.size());
        if (!n || !m) return {};
        
        using mint = static_modint<mod>;
        std::vector<mint> a2(n), b2(m);
        for (int i = 0; i < n; i++) {
            a2[i] = mint(a[i]);
        }
        for (int i = 0; i < m; i++) {
            b2[i] = mint(b[i]);
        }
        auto c2 = convolution(move(a2), move(b2));
        std::vector<T> c(n + m - 1);
        for (int i = 0; i < n + m - 1; i++) {
            c[i] = c2[i].val();
        }
        return c;
    }
    
    std::vector<long long> convolution_ll(const std::vector<long long>& a,
                                          const std::vector<long long>& b) {
        int n = int(a.size()), m = int(b.size());
        if (!n || !m) return {};
        
        static constexpr unsigned long long MOD1 = 754974721;  // 2^24
        static constexpr unsigned long long MOD2 = 167772161;  // 2^25
        static constexpr unsigned long long MOD3 = 469762049;  // 2^26
        static constexpr unsigned long long M2M3 = MOD2 * MOD3;
        static constexpr unsigned long long M1M3 = MOD1 * MOD3;
        static constexpr unsigned long long M1M2 = MOD1 * MOD2;
        static constexpr unsigned long long M1M2M3 = MOD1 * MOD2 * MOD3;
        
        static constexpr unsigned long long i1 =
        internal::inv_gcd(MOD2 * MOD3, MOD1).second;
        static constexpr unsigned long long i2 =
        internal::inv_gcd(MOD1 * MOD3, MOD2).second;
        static constexpr unsigned long long i3 =
        internal::inv_gcd(MOD1 * MOD2, MOD3).second;
        
        auto c1 = convolution<MOD1>(a, b);
        auto c2 = convolution<MOD2>(a, b);
        auto c3 = convolution<MOD3>(a, b);
        
        std::vector<long long> c(n + m - 1);
        for (int i = 0; i < n + m - 1; i++) {
            unsigned long long x = 0;
            x += (c1[i] * i1) % MOD1 * M2M3;
            x += (c2[i] * i2) % MOD2 * M1M3;
            x += (c3[i] * i3) % MOD3 * M1M2;
            long long diff =
            c1[i] - internal::safe_mod((long long)(x), (long long)(MOD1));
            if (diff < 0) diff += MOD1;
            static constexpr unsigned long long offset[5] = {
                0, 0, M1M2M3, 2 * M1M2M3, 3 * M1M2M3};
            x -= offset[diff % 5];
            c[i] = x;
        }
        
        return c;
    }
    
}  // namespace atcoder

//幾何ライブラリ
// 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);
}

typedef Segment Line;

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);
}

const int D=100000;

int main(){
    
    std::ifstream in("text.txt");
    std::cin.rdbuf(in.rdbuf());
    cin.tie(0);
    ios::sync_with_stdio(false);
    
    int AA,BB,CC;cin>>AA>>BB>>CC;
    map<Point,ll> A,B,C;
    for(int i=0;i<AA;i++){
        Point p;cin>>p.x>>p.y;
        //p=p*2;
        A[p]++;
    }
    for(int i=0;i<BB;i++){
        Point p;cin>>p.x>>p.y;
        //p=p*2;
        B[p]++;
    }
    for(int i=0;i<CC;i++){
        Point p;cin>>p.x>>p.y;
        //p=p*2;
        C[p]++;
    }
    
    if(si(A)==1||si(B)==1){
        ll ans=0;
        for(auto a:A){
            for(auto b:B){
                Point aa=a.fi,bb=b.fi;
                Point p=aa+bb;
                p=p/2;
                if(C.count(p)) ans+=a.se*b.se*C[p];
            }
        }
        cout<<ans<<"\n";
        return 0;
    }
    if(si(C)==1){
        ll ans=0;
        for(auto a:A){
            for(auto c:C){
                Point aa=a.fi,cc=c.fi;
                Point p=cc+cc-aa;
                if(B.count(p)) ans+=a.se*c.se*B[p];
            }
        }
        cout<<ans<<"\n";
        return 0;
    }
    
    Line al={(*A.begin()).fi,(*A.rbegin()).fi};
    Line bl={(*B.begin()).fi,(*B.rbegin()).fi};
    Line cl={(*C.begin()).fi,(*C.rbegin()).fi};
    
    ll ans=0;
    
    if(isParallel(al,bl)){
        if(al.p1.x==al.p2.x){
            vector<ll> X(2*D+1),Y(2*D+1);
            for(auto a:A){
                X[(int)(a.fi.y)+D]+=a.se;
            }
            for(auto a:B){
                Y[(int)(a.fi.y)+D]+=a.se;
            }
            auto Z=atcoder::convolution_ll(X,Y);
            for(int i=0;i<si(Z);i++){
                ll y=i-D-D;
                Point p={(al.p1.x+bl.p1.x)/2,(double)(y)/2};
                if(C.count(p)){
                    ans+=Z[i]*C[p];
                }
            }
        }else{
            vector<ll> X(2*D+1),Y(2*D+1);
            for(auto a:A){
                X[(int)(a.fi.x)+D]+=a.se;
            }
            for(auto a:B){
                Y[(int)(a.fi.x)+D]+=a.se;
            }
            double kata=(al.p2.y-al.p1.y)/(al.p2.x-al.p1.x);
            double sep1=al.p1.y-kata*al.p1.x;
            double sep2=bl.p1.y-kata*bl.p1.x;
            //cout<<kata<<" "<<sep<<endl;
            auto Z=atcoder::convolution_ll(X,Y);
            for(int i=0;i<si(Z);i++){
                double x=(double)(i-D-D)/2,y=kata*x+(sep1+sep2)/2.0;
                Point p={x,y};
                if(C.count(p)){
                    ans+=Z[i]*C[p];
                }
            }
        }
    }else{
        for(auto c:C){
            Point cc=c.fi;
            Line L={{cc+cc-al.p1},{cc+cc-al.p2}};
            Point b=getCrossPointL(L,bl);
            if(B.count(b)){
                Point a=cc+cc-b;
                if(A.count(a)){
                    ans+=A[a]*B[b]*c.se;
                }
            }
        }
    }
    
    cout<<ans<<"\n";
}
accuracy: 1
time_ms: 270
memory_kb: 40116
final_rank: 4

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,INF=1<<30;

//modint+畳み込み+逆元テーブル

// from: https://gist.github.com/yosupo06/ddd51afb727600fd95d9d8ad6c3c80c9
// (based on AtCoder STL)

#include <algorithm>
#include <array>

#ifdef _MSC_VER
#include <intrin.h>
#endif

namespace atcoder {
    
    namespace internal {
        
        int ceil_pow2(int n) {
            int x = 0;
            while ((1U << x) < (unsigned int)(n)) x++;
            return x;
        }
        
        int bsf(unsigned int n) {
#ifdef _MSC_VER
            unsigned long index;
            _BitScanForward(&index, n);
            return index;
#else
            return __builtin_ctz(n);
#endif
        }
        
    }  // namespace internal
    
}  // namespace atcoder



#include <utility>

namespace atcoder {
    
    namespace internal {
        
        constexpr long long safe_mod(long long x, long long m) {
            x %= m;
            if (x < 0) x += m;
            return x;
        }
        
        struct barrett {
            unsigned int _m;
            unsigned long long im;
            
            barrett(unsigned int m) : _m(m), im((unsigned long long)(-1) / m + 1) {}
            
            unsigned int umod() const { return _m; }
            
            unsigned int mul(unsigned int a, unsigned int b) const {
                
                unsigned long long z = a;
                z *= b;
#ifdef _MSC_VER
                unsigned long long x;
                _umul128(z, im, &x);
#else
                unsigned long long x =
                (unsigned long long)(((unsigned __int128)(z)*im) >> 64);
#endif
                unsigned int v = (unsigned int)(z - x * _m);
                if (_m <= v) v += _m;
                return v;
            }
        };
        
        constexpr long long pow_mod_constexpr(long long x, long long n, int m) {
            if (m == 1) return 0;
            unsigned int _m = (unsigned int)(m);
            unsigned long long r = 1;
            unsigned long long y = safe_mod(x, m);
            while (n) {
                if (n & 1) r = (r * y) % _m;
                y = (y * y) % _m;
                n >>= 1;
            }
            return r;
        }
        
        constexpr bool is_prime_constexpr(int n) {
            if (n <= 1) return false;
            if (n == 2 || n == 7 || n == 61) return true;
            if (n % 2 == 0) return false;
            long long d = n - 1;
            while (d % 2 == 0) d /= 2;
            for (long long a : {2, 7, 61}) {
                long long t = d;
                long long y = pow_mod_constexpr(a, t, n);
                while (t != n - 1 && y != 1 && y != n - 1) {
                    y = y * y % n;
                    t <<= 1;
                }
                if (y != n - 1 && t % 2 == 0) {
                    return false;
                }
            }
            return true;
        }
        template <int n> constexpr bool is_prime = is_prime_constexpr(n);
        
        constexpr std::pair<long long, long long> inv_gcd(long long a, long long b) {
            a = safe_mod(a, b);
            if (a == 0) return {b, 0};
            
            long long s = b, t = a;
            long long m0 = 0, m1 = 1;
            
            while (t) {
                long long u = s / t;
                s -= t * u;
                m0 -= m1 * u;  // |m1 * u| <= |m1| * s <= b
                
                
                auto tmp = s;
                s = t;
                t = tmp;
                tmp = m0;
                m0 = m1;
                m1 = tmp;
            }
            if (m0 < 0) m0 += b / s;
            return {s, m0};
        }
        
        constexpr int primitive_root_constexpr(int m) {
            if (m == 2) return 1;
            if (m == 167772161) return 3;
            if (m == 469762049) return 3;
            if (m == 754974721) return 11;
            if (m == 998244353) return 3;
            int divs[20] = {};
            divs[0] = 2;
            int cnt = 1;
            int x = (m - 1) / 2;
            while (x % 2 == 0) x /= 2;
            for (int i = 3; (long long)(i)*i <= x; i += 2) {
                if (x % i == 0) {
                    divs[cnt++] = i;
                    while (x % i == 0) {
                        x /= i;
                    }
                }
            }
            if (x > 1) {
                divs[cnt++] = x;
            }
            for (int g = 2;; g++) {
                bool ok = true;
                for (int i = 0; i < cnt; i++) {
                    if (pow_mod_constexpr(g, (m - 1) / divs[i], m) == 1) {
                        ok = false;
                        break;
                    }
                }
                if (ok) return g;
            }
        }
        template <int m> constexpr int primitive_root = primitive_root_constexpr(m);
        
    }  // namespace internal
    
}  // namespace atcoder


#include <cassert>
#include <numeric>
#include <type_traits>

namespace atcoder {
    
    namespace internal {
        
#ifndef _MSC_VER
        template <class T>
        using is_signed_int128 =
        typename std::conditional<std::is_same<T, __int128_t>::value ||
        std::is_same<T, __int128>::value,
        std::true_type,
        std::false_type>::type;
        
        template <class T>
        using is_unsigned_int128 =
        typename std::conditional<std::is_same<T, __uint128_t>::value ||
        std::is_same<T, unsigned __int128>::value,
        std::true_type,
        std::false_type>::type;
        
        template <class T>
        using make_unsigned_int128 =
        typename std::conditional<std::is_same<T, __int128_t>::value,
        __uint128_t,
        unsigned __int128>;
        
        template <class T>
        using is_integral = typename std::conditional<std::is_integral<T>::value ||
        is_signed_int128<T>::value ||
        is_unsigned_int128<T>::value,
        std::true_type,
        std::false_type>::type;
        
        template <class T>
        using is_signed_int = typename std::conditional<(is_integral<T>::value &&
                                                         std::is_signed<T>::value) ||
        is_signed_int128<T>::value,
        std::true_type,
        std::false_type>::type;
        
        template <class T>
        using is_unsigned_int =
        typename std::conditional<(is_integral<T>::value &&
                                   std::is_unsigned<T>::value) ||
        is_unsigned_int128<T>::value,
        std::true_type,
        std::false_type>::type;
        
        template <class T>
        using to_unsigned = typename std::conditional<
        is_signed_int128<T>::value,
        make_unsigned_int128<T>,
        typename std::conditional<std::is_signed<T>::value,
        std::make_unsigned<T>,
        std::common_type<T>>::type>::type;
        
#else
        
        template <class T> using is_integral = typename std::is_integral<T>;
        
        template <class T>
        using is_signed_int =
        typename std::conditional<is_integral<T>::value && std::is_signed<T>::value,
        std::true_type,
        std::false_type>::type;
        
        template <class T>
        using is_unsigned_int =
        typename std::conditional<is_integral<T>::value &&
        std::is_unsigned<T>::value,
        std::true_type,
        std::false_type>::type;
        
        template <class T>
        using to_unsigned = typename std::conditional<is_signed_int<T>::value,
        std::make_unsigned<T>,
        std::common_type<T>>::type;
        
#endif
        
        template <class T>
        using is_signed_int_t = std::enable_if_t<is_signed_int<T>::value>;
        
        template <class T>
        using is_unsigned_int_t = std::enable_if_t<is_unsigned_int<T>::value>;
        
        template <class T> using to_unsigned_t = typename to_unsigned<T>::type;
        
    }  // namespace internal
    
}  // namespace atcoder

#include <cassert>
#include <numeric>
#include <type_traits>

#ifdef _MSC_VER
#include <intrin.h>
#endif

namespace atcoder {
    
    namespace internal {
        
        struct modint_base {};
        struct static_modint_base : modint_base {};
        
        template <class T> using is_modint = std::is_base_of<modint_base, T>;
        template <class T> using is_modint_t = std::enable_if_t<is_modint<T>::value>;
        
    }  // namespace internal
    
    template <int m, std::enable_if_t<(1 <= m)>* = nullptr>
    struct static_modint : internal::static_modint_base {
        using mint = static_modint;
        
    public:
        static constexpr int mod() { return m; }
        static mint raw(int v) {
            mint x;
            x._v = v;
            return x;
        }
        
        static_modint() : _v(0) {}
        template <class T, internal::is_signed_int_t<T>* = nullptr>
        static_modint(T v) {
            long long x = (long long)(v % (long long)(umod()));
            if (x < 0) x += umod();
            _v = (unsigned int)(x);
        }
        template <class T, internal::is_unsigned_int_t<T>* = nullptr>
        static_modint(T v) {
            _v = (unsigned int)(v % umod());
        }
        static_modint(bool v) { _v = ((unsigned int)(v) % umod()); }
        
        unsigned int val() const { return _v; }
        
        mint& operator++() {
            _v++;
            if (_v == umod()) _v = 0;
            return *this;
        }
        mint& operator--() {
            if (_v == 0) _v = umod();
            _v--;
            return *this;
        }
        mint operator++(int) {
            mint result = *this;
            ++*this;
            return result;
        }
        mint operator--(int) {
            mint result = *this;
            --*this;
            return result;
        }
        
        mint& operator+=(const mint& rhs) {
            _v += rhs._v;
            if (_v >= umod()) _v -= umod();
            return *this;
        }
        mint& operator-=(const mint& rhs) {
            _v -= rhs._v;
            if (_v >= umod()) _v += umod();
            return *this;
        }
        mint& operator*=(const mint& rhs) {
            unsigned long long z = _v;
            z *= rhs._v;
            _v = (unsigned int)(z % umod());
            return *this;
        }
        mint& operator/=(const mint& rhs) { return *this = *this * rhs.inv(); }
        
        mint operator+() const { return *this; }
        mint operator-() const { return mint() - *this; }
        
        mint pow(long long n) const {
            assert(0 <= n);
            mint x = *this, r = 1;
            while (n) {
                if (n & 1) r *= x;
                x *= x;
                n >>= 1;
            }
            return r;
        }
        mint inv() const {
            if (prime) {
                assert(_v);
                return pow(umod() - 2);
            } else {
                auto eg = internal::inv_gcd(_v, m);
                assert(eg.first == 1);
                return eg.second;
            }
        }
        
        friend mint operator+(const mint& lhs, const mint& rhs) {
            return mint(lhs) += rhs;
        }
        friend mint operator-(const mint& lhs, const mint& rhs) {
            return mint(lhs) -= rhs;
        }
        friend mint operator*(const mint& lhs, const mint& rhs) {
            return mint(lhs) *= rhs;
        }
        friend mint operator/(const mint& lhs, const mint& rhs) {
            return mint(lhs) /= rhs;
        }
        friend bool operator==(const mint& lhs, const mint& rhs) {
            return lhs._v == rhs._v;
        }
        friend bool operator!=(const mint& lhs, const mint& rhs) {
            return lhs._v != rhs._v;
        }
        
    private:
        unsigned int _v;
        static constexpr unsigned int umod() { return m; }
        static constexpr bool prime = internal::is_prime<m>;
    };
    
    template <int id> struct dynamic_modint : internal::modint_base {
        using mint = dynamic_modint;
        
    public:
        static int mod() { return (int)(bt.umod()); }
        static void set_mod(int m) {
            assert(1 <= m);
            bt = internal::barrett(m);
        }
        static mint raw(int v) {
            mint x;
            x._v = v;
            return x;
        }
        
        dynamic_modint() : _v(0) {}
        template <class T, internal::is_signed_int_t<T>* = nullptr>
        dynamic_modint(T v) {
            long long x = (long long)(v % (long long)(mod()));
            if (x < 0) x += mod();
            _v = (unsigned int)(x);
        }
        template <class T, internal::is_unsigned_int_t<T>* = nullptr>
        dynamic_modint(T v) {
            _v = (unsigned int)(v % mod());
        }
        dynamic_modint(bool v) { _v = ((unsigned int)(v) % mod()); }
        
        unsigned int val() const { return _v; }
        
        mint& operator++() {
            _v++;
            if (_v == umod()) _v = 0;
            return *this;
        }
        mint& operator--() {
            if (_v == 0) _v = umod();
            _v--;
            return *this;
        }
        mint operator++(int) {
            mint result = *this;
            ++*this;
            return result;
        }
        mint operator--(int) {
            mint result = *this;
            --*this;
            return result;
        }
        
        mint& operator+=(const mint& rhs) {
            _v += rhs._v;
            if (_v >= umod()) _v -= umod();
            return *this;
        }
        mint& operator-=(const mint& rhs) {
            _v += mod() - rhs._v;
            if (_v >= umod()) _v -= umod();
            return *this;
        }
        mint& operator*=(const mint& rhs) {
            _v = bt.mul(_v, rhs._v);
            return *this;
        }
        mint& operator/=(const mint& rhs) { return *this = *this * rhs.inv(); }
        
        mint operator+() const { return *this; }
        mint operator-() const { return mint() - *this; }
        
        mint pow(long long n) const {
            assert(0 <= n);
            mint x = *this, r = 1;
            while (n) {
                if (n & 1) r *= x;
                x *= x;
                n >>= 1;
            }
            return r;
        }
        mint inv() const {
            auto eg = internal::inv_gcd(_v, mod());
            assert(eg.first == 1);
            return eg.second;
        }
        
        friend mint operator+(const mint& lhs, const mint& rhs) {
            return mint(lhs) += rhs;
        }
        friend mint operator-(const mint& lhs, const mint& rhs) {
            return mint(lhs) -= rhs;
        }
        friend mint operator*(const mint& lhs, const mint& rhs) {
            return mint(lhs) *= rhs;
        }
        friend mint operator/(const mint& lhs, const mint& rhs) {
            return mint(lhs) /= rhs;
        }
        friend bool operator==(const mint& lhs, const mint& rhs) {
            return lhs._v == rhs._v;
        }
        friend bool operator!=(const mint& lhs, const mint& rhs) {
            return lhs._v != rhs._v;
        }
        
    private:
        unsigned int _v;
        static internal::barrett bt;
        static unsigned int umod() { return bt.umod(); }
    };
    template <int id> internal::barrett dynamic_modint<id>::bt = 998244353;
    
    using modint998244353 = static_modint<998244353>;
    using modint1000000007 = static_modint<1000000007>;
    using modint = dynamic_modint<-1>;
    
    namespace internal {
        
        template <class T>
        using is_static_modint = std::is_base_of<internal::static_modint_base, T>;
        
        template <class T>
        using is_static_modint_t = std::enable_if_t<is_static_modint<T>::value>;
        
        template <class> struct is_dynamic_modint : public std::false_type {};
        template <int id>
        struct is_dynamic_modint<dynamic_modint<id>> : public std::true_type {};
        
        template <class T>
        using is_dynamic_modint_t = std::enable_if_t<is_dynamic_modint<T>::value>;
        
    }  // namespace internal
    
}  // namespace atcoder

#include <cassert>
#include <type_traits>
#include <vector>

namespace atcoder {
    
    namespace internal {
        
        template <class mint, internal::is_static_modint_t<mint>* = nullptr>
        void butterfly(std::vector<mint>& a) {
            static constexpr int g = internal::primitive_root<mint::mod()>;
            int n = int(a.size());
            int h = internal::ceil_pow2(n);
            
            static bool first = true;
            static mint sum_e[30];  // sum_e[i] = ies[0] * ... * ies[i - 1] * es[i]
            if (first) {
                first = false;
                mint es[30], ies[30];  // es[i]^(2^(2+i)) == 1
                int cnt2 = bsf(mint::mod() - 1);
                mint e = mint(g).pow((mint::mod() - 1) >> cnt2), ie = e.inv();
                for (int i = cnt2; i >= 2; i--) {
                    es[i - 2] = e;
                    ies[i - 2] = ie;
                    e *= e;
                    ie *= ie;
                }
                mint now = 1;
                for (int i = 0; i < cnt2 - 2; i++) {
                    sum_e[i] = es[i] * now;
                    now *= ies[i];
                }
            }
            for (int ph = 1; ph <= h; ph++) {
                int w = 1 << (ph - 1), p = 1 << (h - ph);
                mint now = 1;
                for (int s = 0; s < w; s++) {
                    int offset = s << (h - ph + 1);
                    for (int i = 0; i < p; i++) {
                        auto l = a[i + offset];
                        auto r = a[i + offset + p] * now;
                        a[i + offset] = l + r;
                        a[i + offset + p] = l - r;
                    }
                    now *= sum_e[bsf(~(unsigned int)(s))];
                }
            }
        }
        
        template <class mint, internal::is_static_modint_t<mint>* = nullptr>
        void butterfly_inv(std::vector<mint>& a) {
            static constexpr int g = internal::primitive_root<mint::mod()>;
            int n = int(a.size());
            int h = internal::ceil_pow2(n);
            
            static bool first = true;
            static mint sum_ie[30];  // sum_ie[i] = es[0] * ... * es[i - 1] * ies[i]
            if (first) {
                first = false;
                mint es[30], ies[30];  // es[i]^(2^(2+i)) == 1
                int cnt2 = bsf(mint::mod() - 1);
                mint e = mint(g).pow((mint::mod() - 1) >> cnt2), ie = e.inv();
                for (int i = cnt2; i >= 2; i--) {
                    es[i - 2] = e;
                    ies[i - 2] = ie;
                    e *= e;
                    ie *= ie;
                }
                mint now = 1;
                for (int i = 0; i < cnt2 - 2; i++) {
                    sum_ie[i] = ies[i] * now;
                    now *= es[i];
                }
            }
            
            for (int ph = h; ph >= 1; ph--) {
                int w = 1 << (ph - 1), p = 1 << (h - ph);
                mint inow = 1;
                for (int s = 0; s < w; s++) {
                    int offset = s << (h - ph + 1);
                    for (int i = 0; i < p; i++) {
                        auto l = a[i + offset];
                        auto r = a[i + offset + p];
                        a[i + offset] = l + r;
                        a[i + offset + p] =
                        (unsigned long long)(mint::mod() + l.val() - r.val()) *
                        inow.val();
                    }
                    inow *= sum_ie[bsf(~(unsigned int)(s))];
                }
            }
        }
        
    }  // namespace internal
    
    template <class mint, internal::is_static_modint_t<mint>* = nullptr>
    std::vector<mint> convolution(std::vector<mint> a, std::vector<mint> b) {
        int n = int(a.size()), m = int(b.size());
        if (!n || !m) return {};
        if (std::min(n, m) <= 60) {
            if (n < m) {
                std::swap(n, m);
                std::swap(a, b);
            }
            std::vector<mint> ans(n + m - 1);
            for (int i = 0; i < n; i++) {
                for (int j = 0; j < m; j++) {
                    ans[i + j] += a[i] * b[j];
                }
            }
            return ans;
        }
        int z = 1 << internal::ceil_pow2(n + m - 1);
        a.resize(z);
        internal::butterfly(a);
        b.resize(z);
        internal::butterfly(b);
        for (int i = 0; i < z; i++) {
            a[i] *= b[i];
        }
        internal::butterfly_inv(a);
        a.resize(n + m - 1);
        mint iz = mint(z).inv();
        for (int i = 0; i < n + m - 1; i++) a[i] *= iz;
        return a;
    }
    
    template <unsigned int mod = 998244353,
    class T,
    std::enable_if_t<internal::is_integral<T>::value>* = nullptr>
    std::vector<T> convolution(const std::vector<T>& a, const std::vector<T>& b) {
        int n = int(a.size()), m = int(b.size());
        if (!n || !m) return {};
        
        using mint = static_modint<mod>;
        std::vector<mint> a2(n), b2(m);
        for (int i = 0; i < n; i++) {
            a2[i] = mint(a[i]);
        }
        for (int i = 0; i < m; i++) {
            b2[i] = mint(b[i]);
        }
        auto c2 = convolution(move(a2), move(b2));
        std::vector<T> c(n + m - 1);
        for (int i = 0; i < n + m - 1; i++) {
            c[i] = c2[i].val();
        }
        return c;
    }
    
    std::vector<long long> convolution_ll(const std::vector<long long>& a,
                                          const std::vector<long long>& b) {
        int n = int(a.size()), m = int(b.size());
        if (!n || !m) return {};
        
        static constexpr unsigned long long MOD1 = 754974721;  // 2^24
        static constexpr unsigned long long MOD2 = 167772161;  // 2^25
        static constexpr unsigned long long MOD3 = 469762049;  // 2^26
        static constexpr unsigned long long M2M3 = MOD2 * MOD3;
        static constexpr unsigned long long M1M3 = MOD1 * MOD3;
        static constexpr unsigned long long M1M2 = MOD1 * MOD2;
        static constexpr unsigned long long M1M2M3 = MOD1 * MOD2 * MOD3;
        
        static constexpr unsigned long long i1 =
        internal::inv_gcd(MOD2 * MOD3, MOD1).second;
        static constexpr unsigned long long i2 =
        internal::inv_gcd(MOD1 * MOD3, MOD2).second;
        static constexpr unsigned long long i3 =
        internal::inv_gcd(MOD1 * MOD2, MOD3).second;
        
        auto c1 = convolution<MOD1>(a, b);
        auto c2 = convolution<MOD2>(a, b);
        auto c3 = convolution<MOD3>(a, b);
        
        std::vector<long long> c(n + m - 1);
        for (int i = 0; i < n + m - 1; i++) {
            unsigned long long x = 0;
            x += (c1[i] * i1) % MOD1 * M2M3;
            x += (c2[i] * i2) % MOD2 * M1M3;
            x += (c3[i] * i3) % MOD3 * M1M2;
            long long diff =
            c1[i] - internal::safe_mod((long long)(x), (long long)(MOD1));
            if (diff < 0) diff += MOD1;
            static constexpr unsigned long long offset[5] = {
                0, 0, M1M2M3, 2 * M1M2M3, 3 * M1M2M3};
            x -= offset[diff % 5];
            c[i] = x;
        }
        
        return c;
    }
    
}  // namespace atcoder

//幾何ライブラリ
// 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);
}

typedef Segment Line;

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);
}

const int D=100000;

int main(){
    
    std::ifstream in("text.txt");
    std::cin.rdbuf(in.rdbuf());
    cin.tie(0);
    ios::sync_with_stdio(false);
    
    int AA,BB,CC;cin>>AA>>BB>>CC;
    map<Point,ll> A,B,C;
    for(int i=0;i<AA;i++){
        Point p;cin>>p.x>>p.y;
        //p=p*2;
        A[p]++;
    }
    for(int i=0;i<BB;i++){
        Point p;cin>>p.x>>p.y;
        //p=p*2;
        B[p]++;
    }
    for(int i=0;i<CC;i++){
        Point p;cin>>p.x>>p.y;
        //p=p*2;
        C[p]++;
    }
    
    if(si(A)==1||si(B)==1){
        ll ans=0;
        for(auto a:A){
            for(auto b:B){
                Point aa=a.fi,bb=b.fi;
                Point p=aa+bb;
                p=p/2;
                if(C.count(p)) ans+=a.se*b.se*C[p];
            }
        }
        cout<<ans<<"\n";
        return 0;
    }
    if(si(C)==1){
        ll ans=0;
        for(auto a:A){
            for(auto c:C){
                Point aa=a.fi,cc=c.fi;
                Point p=cc+cc-aa;
                if(B.count(p)) ans+=a.se*c.se*B[p];
            }
        }
        cout<<ans<<"\n";
        return 0;
    }
    
    Line al={(*A.begin()).fi,(*A.rbegin()).fi};
    Line bl={(*B.begin()).fi,(*B.rbegin()).fi};
    Line cl={(*C.begin()).fi,(*C.rbegin()).fi};
    
    ll ans=0;
    
    if(isParallel(al,bl)){
        if(al.p1.x==al.p2.x){
            vector<ll> X(2*D+1),Y(2*D+1);
            for(auto a:A){
                X[(int)(a.fi.y)+D]+=a.se;
            }
            for(auto a:B){
                Y[(int)(a.fi.y)+D]+=a.se;
            }
            auto Z=atcoder::convolution_ll(X,Y);
            for(int i=0;i<si(Z);i++){
                ll y=i-D-D;
                Point p={0.0,(double)(y)/2};
                if(C.count(p)){
                    ans+=Z[i]*C[p];
                }
            }
        }else{
            vector<ll> X(2*D+1),Y(2*D+1);
            for(auto a:A){
                X[(int)(a.fi.x)+D]+=a.se;
            }
            for(auto a:B){
                Y[(int)(a.fi.x)+D]+=a.se;
            }
            double kata=(al.p2.y-al.p1.y)/(al.p2.x-al.p1.x);
            double sep1=al.p1.y-kata*al.p1.x;
            double sep2=bl.p1.y-kata*bl.p1.x;
            //cout<<kata<<" "<<sep<<endl;
            auto Z=atcoder::convolution_ll(X,Y);
            for(int i=0;i<si(Z);i++){
                double x=(double)(i-D-D)/2,y=kata*x+(sep1+sep2)/2.0;
                Point p={x,y};
                if(C.count(p)){
                    ans+=Z[i]*C[p];
                }
            }
        }
    }else{
        for(auto c:C){
            Point cc=c.fi;
            Line L={{cc+cc-al.p1},{cc+cc-al.p2}};
            Point b=getCrossPointL(L,bl);
            if(B.count(b)){
                Point a=cc+cc-b;
                if(A.count(a)){
                    ans+=A[a]*B[b]*c.se;
                }
            }
        }
    }
    
    cout<<ans<<"\n";
}
accuracy: 0.3728813559322034
time_ms: 130
memory_kb: 21404
final_rank: 13

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 200005
#define MAX 30

typedef complex<double> COMPLEX;


struct LOC{

	ll x,y;
};

struct Info{
	Info(int arg_left,int arg_right){
		left = arg_left;
		right = arg_right;
	}
	int left,right;
};

struct Info2{

	bool operator<(const struct Info2 &arg) const{

		return value < arg.value;
	}

	double value;
	ll num;
};

struct Data{
	void set(ll arg_denominator,ll arg_numerator){
        denominator = arg_denominator; //分母
        numerator = arg_numerator;
  	}
	ll denominator,numerator;
};

struct Pos{


	Data slope,add;
};


int LR_rev[2000005];
vector<Info> info;
vector<COMPLEX> conv_V[SIZE];
int POW[SIZE];

void calc_swap_pair(int N,int num_pow){

	LR_rev[0] = 0;

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

		if(i%2 == 1){

			LR_rev[i] = LR_rev[i-1]+POW[num_pow-1]; //1を足す代わりにPOW[num_pow-1]を足す

		}else{

			LR_rev[i] = LR_rev[i/2]/2; //半分のインデックスの値に、2を掛ける代わりに2で割る
		}

		if(i < LR_rev[i]){
			info.push_back(Info(i,LR_rev[i]));
		}
	}
}

void calc_COMPLEX(int N){

	for(int LEN = 2,num_pow = 0; LEN <= N; LEN *= 2,num_pow++){

		conv_V[num_pow].resize(LEN/2);

		conv_V[num_pow][0] = COMPLEX(cos(0),sin(0));

		COMPLEX mult = COMPLEX(cos((2*M_PI)/LEN),sin((2*M_PI)/LEN));

		for(int i = 1; i < LEN/2; i++){

			if(i%2 == 1){
				conv_V[num_pow][i] = conv_V[num_pow][i-1]*mult;
			}else{
				conv_V[num_pow][i] = conv_V[num_pow-1][i/2];
			}
		}
	}
}

//離散フーリエ変換
vector<COMPLEX> DFT(vector<COMPLEX> A) {

	int N = A.size();

	/*偶数項を左に、奇数項を右に仕分けるルールで要素数1まで仕分けした場合の、
	 * 最終結果を先に作っておく(ビットが左右反転したものがその位置に来る)*/
	for(int i = 0; i < info.size(); i++){

		swap(A[info[i].left],A[info[i].right]);
	}

	COMPLEX a,add;

	for(int LEN = 2,num_pow = 0; LEN <= N; LEN *= 2,num_pow++){

		for(int start = 0; start < N; start += LEN){
			for(int i = 0; i < LEN/2; i++){
				//マージソートの容量で、配列を更新していく
				a = A[start+i];
				add = conv_V[num_pow][i]*A[start+LEN/2+i];

				A[start+i] = a+add;
				A[start+LEN/2+i] = a-add;
			}
		}
	}
	return A;
}




//離散逆フーリエ変換
vector<COMPLEX> inverseDFT(vector<COMPLEX> A){

	int N = A.size();

	vector<COMPLEX> TMP = DFT(A);

	//係数を入れ替える&サイズNで各要素を割る
	vector<COMPLEX> RET(N);

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

		RET[i] = TMP[(N-i)%N];
		RET[i] = RET[i]/COMPLEX(N,0);
	}

	return RET;
}

vector<COMPLEX> convolution(vector<COMPLEX> A,vector<COMPLEX> B){

	int degree = (A.size()-1)+(B.size()-1)+1;

	int N = 1,num_pow = 0;
	while(N < degree){
		N *= 2;
		num_pow++;
	}

	info.clear();
	calc_swap_pair(N,num_pow);
	calc_COMPLEX(N);

	A.resize(N);
	B.resize(N);

	A = DFT(A);
	B = DFT(B);

	vector<COMPLEX> RET(N);

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

		RET[i] = A[i]*B[i];
	}

	return inverseDFT(RET);
}

//最大公約数
ll gcd(ll x,ll y){

	x = abs(x);
	y = abs(y);

	if(x < y){
		swap(x,y);
	}
	if(y == 0){
		return x;
	}else{
		return gcd(y,x%y);
	}
}

//最小公倍数
ll lcm(ll x,ll y){

	return (x*y)/gcd(x,y);
}


//傾きと切片を分数で計算して返却する関数
Pos calc_pos(LOC a,LOC b){

	Pos ret;

	if(a.x == b.x){ //垂直

		ret.slope.denominator = 1;
		ret.slope.numerator = BIG_NUM;

	}else if(a.y == b.y){ //水平

		ret.slope.denominator = 1;
		ret.slope.numerator = 0;
		ret.add.denominator = 1;
		ret.add.numerator = a.y;

	}else{

		//★符号に注意★
		ll diff_x = abs(a.x-b.x);
		ll diff_y = abs(a.y-b.y);
		ll common = gcd(diff_x,diff_y);
		diff_x /= common;
		diff_y /= common;

		ret.slope.denominator = diff_x;
		ret.slope.numerator = diff_y;

		if(((a.x-b.x) > 0 && (a.y-b.y) < 0) || ((a.x-b.x) < 0 && (a.y-b.y) > 0)){

			ret.slope.numerator *= -1;
			diff_y *= -1; //マイナスは分子につける
		}

		ll tmp = a.y*diff_x-(diff_y*a.x);
		common = gcd(tmp,diff_x);

		diff_x /= common;
		tmp /= common;

		ret.add.denominator = diff_x;
		ret.add.numerator = tmp;
	}

	return ret;
}

bool is_Parallel(Pos a,Pos b){

	return a.slope.denominator == b.slope.denominator && a.slope.numerator == b.slope.numerator;
}


ll num[3];
ll num_point[3];
vector<int> V[3];
map<pair<ll,ll>,int> MAP[3]; //初出の座標のindexを保持するマップ
ll COUNT[3][SIZE];
ll add_X = 100000,add_Y = 100000;
int A=0,B=1,C=2;
LOC loc[3][SIZE];


int main(){

	POW[0] = 1;
	for(int i = 1; i < MAX; i++){

		POW[i] = POW[i-1]*2;
	}

	for(int i = 0; i < 3; i++){
		//座標の個数
		num_point[i] = 0;
	}
	for(int i = 0; i < 3; i++){
		for(int k = 0; k < SIZE; k++){
			COUNT[i][k] = 0; //同一の点をまとめる
		}
	}

	scanf("%lld %lld %lld",&num[A],&num[B],&num[C]);

	for(int loop = 0; loop < 3; loop++){
		for(int i = 0; i < num[loop]; i++){

			scanf("%lld %lld",&loc[loop][i].x,&loc[loop][i].y);
			loc[loop][i].x += add_X;
			loc[loop][i].y += add_Y;

			auto at = MAP[loop].find(make_pair(loc[loop][i].x,loc[loop][i].y));

			if(at == MAP[loop].end()){ //初めて出た座標

				MAP[loop][make_pair(loc[loop][i].x,loc[loop][i].y)] = i; //インデックスを記録

				V[loop].push_back(i);
				num_point[loop]++;
				COUNT[loop][i] = 1;

			}else{

				COUNT[loop][at->second]++;
			}
		}
	}

	ll ans;
	ll a_x,a_y,b_x,b_y,c_x,c_y;

	if((num_point[A] == 1)||(num_point[B] == 1)){ //AがBが1点の場合

		//printf("片方が1点\n");

		ans = 0;
		for(int i = 0; i < V[A].size(); i++){

			a_x = loc[A][V[A][i]].x;
			a_y = loc[A][V[A][i]].y;

			for(int k = 0; k < V[B].size(); k++){

				b_x = loc[B][V[B][k]].x;
				b_y = loc[B][V[B][k]].y;

				if((a_x+b_x)%2 == 1 || (a_y+b_y)%2 == 1)continue;

				c_x = (a_x+b_x)/2;
				c_y = (a_y+b_y)/2;

				auto at = MAP[C].find(make_pair(c_x,c_y));
				if(at == MAP[C].end())continue;

				ans += COUNT[A][V[A][i]]*COUNT[B][V[B][k]]*COUNT[C][at->second];
			}
		}

		printf("%lld\n",ans);
		return 0;
	}

	//AとBの傾きを計算
	Pos pos[3];

	pos[A] = calc_pos(loc[A][V[A][0]],loc[A][V[A][1]]);
	pos[B] = calc_pos(loc[B][V[B][0]],loc[B][V[B][1]]);

	double slope_A = (double)pos[A].slope.numerator/(double)pos[A].slope.denominator;
	double add_A = (double)pos[A].add.numerator/(double)pos[A].add.denominator;

	double slope_B = (double)pos[B].slope.numerator/(double)pos[B].slope.denominator;
	double add_B = (double)pos[B].add.numerator/(double)pos[B].add.denominator;

	double d_x_a,d_x_b,d_x_c,d_y_a,d_y_c;

	if(!is_Parallel(pos[A],pos[B])){ //AとBが平行でない場合

		if(pos[B].slope.numerator == BIG_NUM){ //Bが垂直

			swap(A,B); //Aを垂直にする
			swap(slope_A,slope_B);
			swap(add_A,add_B);
		}

		//整数のまま演算すると桁あふれするので実数でやる
		vector<Info2> info_A,info_B;
		vector<double> v_A,v_B;

		for(int i = 0; i < V[A].size(); i++){
			Info2 tmp_info;
			if(pos[A].slope.numerator == BIG_NUM){ //Aが垂直

				tmp_info.value = loc[A][V[A][i]].y; //垂直ならy座標

			}else{

				tmp_info.value = loc[A][V[A][i]].x; //垂直でないならx座標
			}
			v_A.push_back(tmp_info.value);
			tmp_info.num = COUNT[A][V[A][i]]; //重み
			info_A.push_back(tmp_info);
		}
		sort(info_A.begin(),info_A.end());
		sort(v_A.begin(),v_A.end());

		for(int i = 0; i < V[B].size(); i++){
			Info2 tmp_info;
			tmp_info.value = loc[B][V[B][i]].x; //座標
			tmp_info.num = COUNT[B][V[B][i]]; //重み
			v_B.push_back(tmp_info.value);
			info_B.push_back(tmp_info);
		}
		sort(info_B.begin(),info_B.end());
		sort(v_B.begin(),v_B.end());

		ans = 0;

		//Cの座標からA,Bの座標を計算する
		for(int i = 0; i < V[C].size(); i++){

			d_x_c = loc[C][V[C][i]].x;
			d_y_c = loc[C][V[C][i]].y;

			if(pos[A].slope.numerator == BIG_NUM){ //Aが垂直

				d_x_a = loc[A][V[A][0]].x;
				d_x_b = 2*d_x_c-d_x_a;
				d_y_a = 2*d_y_c-(slope_B*d_x_b+add_B);

			}else{ //Aが垂直ではない

				d_x_a = (2*d_y_c-(add_A+2*slope_B*d_x_c+add_B))/(slope_A-slope_B);
				d_x_b = 2*d_x_c-(d_x_a);
			}

			int at_a;

			if(pos[A].slope.numerator == BIG_NUM){ //Aが垂直

				at_a = lower_bound(v_A.begin(),v_A.end(),d_y_a-EPS)-v_A.begin();
				if(at_a == v_A.size() || fabs(d_y_a-info_A[at_a].value) >= EPS)continue;

			}else{

				at_a = lower_bound(v_A.begin(),v_A.end(),d_x_a-EPS)-v_A.begin();
				if(at_a == v_A.size() || fabs(d_x_a-info_A[at_a].value) >= EPS)continue;
			}

			int at_b = lower_bound(v_B.begin(),v_B.end(),d_x_b-EPS)-v_B.begin();
			if(at_b == v_B.size() || fabs(d_x_b-info_B[at_b].value) >= EPS)continue;

			ans += info_A[at_a].num*info_B[at_b].num*COUNT[C][V[C][i]];
		}

		printf("%lld\n",ans);
		return 0;
	}

	//AとBが平行である場合

	if(pos[A].slope.numerator == BIG_NUM && pos[B].slope.numerator == BIG_NUM){ //両方垂直

		if((loc[A][V[A][0]].x+loc[B][V[B][0]].x)%2 == 1){

			printf("0\n");
			return 0;
		}

		ll X = (loc[A][V[A][0]].x+loc[B][V[B][0]].x)/2;

		if(num_point[C] == 1){ //Cが1点だけ

			if(loc[C][V[C][0]].x != X){

				printf("0\n");
				return 0;
			}

			pos[C].slope.denominator = 1;
			pos[C].slope.numerator = BIG_NUM;

		}else{ //Cが2点以上

			pos[C] = calc_pos(loc[C][V[C][0]],loc[C][V[C][1]]);
		}

		if(pos[C].slope.numerator == BIG_NUM){ //Cも垂直

			if(loc[C][V[C][0]].x != X){

				printf("0\n");
				return 0;
			}

			vector<COMPLEX> conv_A(2*SIZE),conv_B(2*SIZE);

			for(int i = 0; i < V[A].size(); i++){

				conv_A[loc[A][V[A][i]].y] += COUNT[A][V[A][i]];
			}
			for(int i = 0; i < V[B].size(); i++){

				conv_B[loc[B][V[B][i]].y] += COUNT[B][V[B][i]];
			}

			vector<COMPLEX> ret = convolution(conv_A,conv_B);

			ans = 0;
			for(int i = 0; i < V[C].size(); i++){ //★★y_a+y_b == 2*y_c★★

				ans += COUNT[C][V[C][i]]*(ll)round(ret[2*loc[C][V[C][i]].y].real());
			}

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

		}else{ //交点は高々1つなので、探す

			vector<int> vec;

			for(ll y = 0; y <= 200000; y++){

				auto at = MAP[C].find(make_pair(X,y));
				if(at == MAP[C].end())continue;

				vec.push_back(at->second);
			}

			if(vec.size() == 0){

				printf("0\n");
				return 0;
			}

			vector<COMPLEX> conv_A(2*SIZE),conv_B(2*SIZE);

			for(int i = 0; i < V[A].size(); i++){

				conv_A[loc[A][V[A][i]].y] += COUNT[A][V[A][i]];
			}
			for(int i = 0; i < V[B].size(); i++){

				conv_B[loc[B][V[B][i]].y] += COUNT[B][V[B][i]];
			}

			vector<COMPLEX> ret = convolution(conv_A,conv_B);

			ans = 0;
			for(int i = 0; i < vec.size(); i++){ //★★x_a+x_b == 2*x_c★★
				ans += COUNT[C][vec[i]]*(ll)round(ret[2*loc[C][vec[i]].y].real());
			}

			printf("%lld\n",ans);
		}

	}else{

		//printf("垂直でない平行\n");

		//AとBの中点を結んでできる直線のposを求める
		pos[C].slope = pos[A].slope;
		ll tmp_add_bunbo = 2*pos[A].add.denominator*pos[B].add.denominator;
		ll tmp_add_bunshi = pos[A].add.numerator*pos[B].add.denominator + pos[B].add.numerator*pos[A].add.denominator;


		ll work_1 = gcd(tmp_add_bunbo,tmp_add_bunshi);
		tmp_add_bunbo /= work_1;
		tmp_add_bunshi /= work_1;

		pos[C].add.denominator = tmp_add_bunbo;
		pos[C].add.numerator = tmp_add_bunshi;

		/*pos[A].debug();
		pos[B].debug();
		pos[C].debug();*/

		vector<int> vec;

		//中点をむすんで出来た直線の点を全探索
		for(ll x = 0; x <= 200000; x++){

			ll bunshi = pos[C].slope.numerator*pos[C].add.denominator*x + pos[C].slope.denominator*pos[C].add.numerator;
			ll bunbo = pos[C].slope.denominator*pos[C].add.denominator;

			if(bunshi%bunbo != 0)continue;

			ll tmp_y = bunshi/bunbo;

			auto at = MAP[C].find(make_pair(x,tmp_y));
			if(at == MAP[C].end())continue;

			vec.push_back(at->second);
		}

		vector<COMPLEX> conv_A(2*SIZE),conv_B(2*SIZE);

		for(int i = 0; i < V[A].size(); i++){

			conv_A[loc[A][V[A][i]].x] += COUNT[A][V[A][i]];
		}
		for(int i = 0; i < V[B].size(); i++){

			conv_B[loc[B][V[B][i]].x] += COUNT[B][V[B][i]];
		}

		vector<COMPLEX> ret = convolution(conv_A,conv_B);

		ans = 0;
		for(int i = 0; i < vec.size(); i++){ //★★x_a+x_b == 2*x_c★★

			ans += COUNT[C][vec[i]]*(ll)round(ret[2*loc[C][vec[i]].x].real());
		}

		printf("%lld\n",ans);
	}

	return 0;
}
accuracy: 1
time_ms: 450
memory_kb: 173024
final_rank: 6

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 200005
#define MAX 30

typedef complex<double> COMPLEX;



struct LOC{

	ll x,y;
};

struct Info{
	Info(int arg_left,int arg_right){
		left = arg_left;
		right = arg_right;
	}
	int left,right;
};

struct Info2{

	bool operator<(const struct Info2 &arg) const{

		return value < arg.value;
	}

	double value;
	ll num;
};

struct Data{
	void set(ll arg_denominator,ll arg_numerator){
        denominator = arg_denominator; //分母
        numerator = arg_numerator;
  	}
	ll denominator,numerator;
};

struct Pos{


	void debug(){

		printf("slope (%lld)/(%lld)  add (%lld)/(%lld)\n",slope.numerator,slope.denominator,add.numerator,add.denominator);
	}

	Data slope,add;
};


int LR_rev[2000005];
vector<Info> info;
vector<COMPLEX> conv_V[SIZE];
int POW[SIZE];

void calc_swap_pair(int N,int num_pow){

	LR_rev[0] = 0;

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

		if(i%2 == 1){

			LR_rev[i] = LR_rev[i-1]+POW[num_pow-1]; //1を足す代わりにPOW[num_pow-1]を足す

		}else{

			LR_rev[i] = LR_rev[i/2]/2; //半分のインデックスの値に、2を掛ける代わりに2で割る
		}

		if(i < LR_rev[i]){
			info.push_back(Info(i,LR_rev[i]));
		}
	}
}

void calc_COMPLEX(int N){

	for(int LEN = 2,num_pow = 0; LEN <= N; LEN *= 2,num_pow++){

		conv_V[num_pow].resize(LEN/2);

		conv_V[num_pow][0] = COMPLEX(cos(0),sin(0));

		COMPLEX mult = COMPLEX(cos((2*M_PI)/LEN),sin((2*M_PI)/LEN));

		for(int i = 1; i < LEN/2; i++){

			if(i%2 == 1){
				conv_V[num_pow][i] = conv_V[num_pow][i-1]*mult;
			}else{
				conv_V[num_pow][i] = conv_V[num_pow-1][i/2];
			}
		}
	}
}

//離散フーリエ変換
vector<COMPLEX> DFT(vector<COMPLEX> A) {

	int N = A.size();

	/*偶数項を左に、奇数項を右に仕分けるルールで要素数1まで仕分けした場合の、
	 * 最終結果を先に作っておく(ビットが左右反転したものがその位置に来る)*/
	for(int i = 0; i < info.size(); i++){

		swap(A[info[i].left],A[info[i].right]);
	}

	COMPLEX a,add;

	for(int LEN = 2,num_pow = 0; LEN <= N; LEN *= 2,num_pow++){

		for(int start = 0; start < N; start += LEN){
			for(int i = 0; i < LEN/2; i++){
				//マージソートの容量で、配列を更新していく
				a = A[start+i];
				add = conv_V[num_pow][i]*A[start+LEN/2+i];

				A[start+i] = a+add;
				A[start+LEN/2+i] = a-add;
			}
		}
	}
	return A;
}




//離散逆フーリエ変換
vector<COMPLEX> inverseDFT(vector<COMPLEX> A){

	int N = A.size();

	vector<COMPLEX> TMP = DFT(A);

	//係数を入れ替える&サイズNで各要素を割る
	vector<COMPLEX> RET(N);

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

		RET[i] = TMP[(N-i)%N];
		RET[i] = RET[i]/COMPLEX(N,0);
	}

	return RET;
}

vector<COMPLEX> convolution(vector<COMPLEX> A,vector<COMPLEX> B){

	int degree = (A.size()-1)+(B.size()-1)+1;

	int N = 1,num_pow = 0;
	while(N < degree){
		N *= 2;
		num_pow++;
	}

	info.clear();
	calc_swap_pair(N,num_pow);
	calc_COMPLEX(N);

	A.resize(N);
	B.resize(N);

	A = DFT(A);
	B = DFT(B);

	vector<COMPLEX> RET(N);

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

		RET[i] = A[i]*B[i];
	}

	return inverseDFT(RET);
}

//最大公約数
ll gcd(ll x,ll y){

	x = abs(x);
	y = abs(y);

	if(x < y){
		swap(x,y);
	}
	if(y == 0){
		return x;
	}else{
		return gcd(y,x%y);
	}
}

//最小公倍数
ll lcm(ll x,ll y){

	return (x*y)/gcd(x,y);
}


//傾きと切片を分数で計算して返却する関数
Pos calc_pos(LOC a,LOC b){

	Pos ret;

	if(a.x == b.x){ //垂直

		ret.slope.denominator = 1;
		ret.slope.numerator = BIG_NUM;

	}else if(a.y == b.y){ //水平

		ret.slope.denominator = 1;
		ret.slope.numerator = 0;
		ret.add.denominator = 1;
		ret.add.numerator = a.y;

	}else{

		//★符号に注意★
		ll diff_x = abs(a.x-b.x);
		ll diff_y = abs(a.y-b.y);
		ll common = gcd(diff_x,diff_y);
		diff_x /= common;
		diff_y /= common;

		ret.slope.denominator = diff_x;
		ret.slope.numerator = diff_y;

		if(((a.x-b.x) > 0 && (a.y-b.y) < 0) || ((a.x-b.x) < 0 && (a.y-b.y) > 0)){

			ret.slope.numerator *= -1;
			diff_y *= -1; //マイナスは分子につける
		}

		//printf("a:(%lld,%lld)\n",a.x,a.y);
		//printf("diff_x:%lld diff_y:%lld\n",diff_x,diff_y);

		ll tmp = a.y*diff_x-(diff_y*a.x);
		common = gcd(tmp,diff_x);

		diff_x /= common;
		tmp /= common;

		ret.add.denominator = diff_x;
		ret.add.numerator = tmp;
	}

	return ret;
}

bool is_Parallel(Pos a,Pos b){

	return a.slope.denominator == b.slope.denominator && a.slope.numerator == b.slope.numerator;
}


ll num[3];
ll num_point[3];
vector<int> V[3];
map<pair<ll,ll>,int> MAP[3]; //初出の座標のindexを保持するマップ
ll COUNT[3][SIZE];
ll add_X = 100000,add_Y = 100000;
int A=0,B=1,C=2;
LOC loc[3][SIZE];


int main(){

	POW[0] = 1;
	for(int i = 1; i < MAX; i++){

		POW[i] = POW[i-1]*2;
	}

	for(int i = 0; i < 3; i++){
		//座標の個数
		num_point[i] = 0;
	}
	for(int i = 0; i < 3; i++){
		for(int k = 0; k < SIZE; k++){
			COUNT[i][k] = 0; //同一の点をまとめる
		}
	}

	scanf("%lld %lld %lld",&num[A],&num[B],&num[C]);

	for(int loop = 0; loop < 3; loop++){
		for(int i = 0; i < num[loop]; i++){

			scanf("%lld %lld",&loc[loop][i].x,&loc[loop][i].y);
			loc[loop][i].x += add_X;
			loc[loop][i].y += add_Y;

			auto at = MAP[loop].find(make_pair(loc[loop][i].x,loc[loop][i].y));

			if(at == MAP[loop].end()){ //初めて出た座標

				MAP[loop][make_pair(loc[loop][i].x,loc[loop][i].y)] = i; //インデックスを記録

				V[loop].push_back(i);
				num_point[loop]++;
				COUNT[loop][i] = 1;

			}else{

				COUNT[loop][at->second]++;
			}
		}
	}

	ll ans;
	ll a_x,a_y,b_x,b_y,c_x,c_y;

	if((num_point[A] == 1)||(num_point[B] == 1)){ //AがBが1点の場合

		//printf("片方が1点\n");

		ans = 0;
		for(int i = 0; i < V[A].size(); i++){

			a_x = loc[A][V[A][i]].x;
			a_y = loc[A][V[A][i]].y;

			for(int k = 0; k < V[B].size(); k++){

				b_x = loc[B][V[B][k]].x;
				b_y = loc[B][V[B][k]].y;

				if((a_x+b_x)%2 == 1 || (a_y+b_y)%2 == 1)continue;

				c_x = (a_x+b_x)/2;
				c_y = (a_y+b_y)/2;

				auto at = MAP[C].find(make_pair(c_x,c_y));
				if(at == MAP[C].end())continue;

				ans += COUNT[A][V[A][i]]*COUNT[B][V[B][k]]*COUNT[C][at->second];
			}
		}

		printf("%lld\n",ans);
		return 0;
	}

	//AとBの傾きを計算
	Pos pos[3];

	pos[A] = calc_pos(loc[A][V[A][0]],loc[A][V[A][1]]);
	pos[B] = calc_pos(loc[B][V[B][0]],loc[B][V[B][1]]);

	//return 0;

	double slope_A = (double)pos[A].slope.numerator/(double)pos[A].slope.denominator;
	double add_A = (double)pos[A].add.numerator/(double)pos[A].add.denominator;

	double slope_B = (double)pos[B].slope.numerator/(double)pos[B].slope.denominator;
	double add_B = (double)pos[B].add.numerator/(double)pos[B].add.denominator;

	double d_x_a,d_x_b,d_x_c,d_y_a,d_y_c;

	if(!is_Parallel(pos[A],pos[B])){ //AとBが平行でない場合

		//printf("AとBが平行でない\n");

		if(pos[B].slope.numerator == BIG_NUM){ //Bが垂直

			swap(A,B); //Aを垂直にする
			swap(slope_A,slope_B);
			swap(add_A,add_B);
		}

		//整数のまま演算すると桁あふれするので実数でやる
		vector<Info2> info_A,info_B;
		vector<double> v_A,v_B;

		for(int i = 0; i < V[A].size(); i++){
			Info2 tmp_info;
			if(pos[A].slope.numerator == BIG_NUM){ //Aが垂直

				tmp_info.value = loc[A][V[A][i]].y; //垂直ならy座標

			}else{

				tmp_info.value = loc[A][V[A][i]].x; //垂直でないならx座標
			}
			v_A.push_back(tmp_info.value);
			tmp_info.num = COUNT[A][V[A][i]]; //重み
			info_A.push_back(tmp_info);
		}
		sort(info_A.begin(),info_A.end());
		sort(v_A.begin(),v_A.end());

		for(int i = 0; i < V[B].size(); i++){
			Info2 tmp_info;
			tmp_info.value = loc[B][V[B][i]].x; //座標
			tmp_info.num = COUNT[B][V[B][i]]; //重み
			v_B.push_back(tmp_info.value);
			info_B.push_back(tmp_info);
		}
		sort(info_B.begin(),info_B.end());
		sort(v_B.begin(),v_B.end());

		ans = 0;

		//Cの座標からA,Bの座標を計算する
		for(int i = 0; i < V[C].size(); i++){

			d_x_c = loc[C][V[C][i]].x;
			d_y_c = loc[C][V[C][i]].y;

			if(pos[A].slope.numerator == BIG_NUM){ //Aが垂直

				d_x_a = loc[A][V[A][0]].x;
				d_x_b = 2*d_x_c-d_x_a;
				d_y_a = 2*d_y_c-(slope_B*d_x_b+add_B);

			}else{ //Aが垂直ではない

				d_x_a = (2*d_y_c-(add_A+2*slope_B*d_x_c+add_B))/(slope_A-slope_B);
				d_x_b = 2*d_x_c-(d_x_a);
			}

			int at_a;

			if(pos[A].slope.numerator == BIG_NUM){ //Aが垂直

				at_a = lower_bound(v_A.begin(),v_A.end(),d_y_a-EPS)-v_A.begin();
				if(at_a == v_A.size() || fabs(d_y_a-info_A[at_a].value) >= EPS)continue;

			}else{

				at_a = lower_bound(v_A.begin(),v_A.end(),d_x_a-EPS)-v_A.begin();
				if(at_a == v_A.size() || fabs(d_x_a-info_A[at_a].value) >= EPS)continue;
			}

			int at_b = lower_bound(v_B.begin(),v_B.end(),d_x_b-EPS)-v_B.begin();
			if(at_b == v_B.size() || fabs(d_x_b-info_B[at_b].value) >= EPS)continue;

			ans += info_A[at_a].num*info_B[at_b].num*COUNT[C][V[C][i]];
		}

		printf("%lld\n",ans);
		return 0;
	}

	//AとBが平行である場合
	//Cが(AとBの中点を結んだ直線上)にあるか否かで場合分け
	//printf("AとBが平行\n");

	if(pos[A].slope.numerator == BIG_NUM && pos[B].slope.numerator == BIG_NUM){ //両方垂直

		if((loc[A][V[A][0]].x+loc[B][V[B][0]].x)%2 == 1){

			printf("0\n");
			return 0;
		}

		ll X = (loc[A][V[A][0]].x+loc[B][V[B][0]].x)/2;

		if(num_point[C] == 1){ //Cが1点だけ

			if(loc[C][V[C][0]].x != X){

				printf("0\n");
				return 0;
			}

			pos[C].slope.denominator = 1;
			pos[C].slope.numerator = BIG_NUM;

		}else{ //Cが2点以上

			pos[C] = calc_pos(loc[C][V[C][0]],loc[C][V[C][1]]);
		}

		if(pos[C].slope.numerator == BIG_NUM){ //Cも垂直

			if(loc[C][V[C][0]].x != X){

				printf("0\n");
				return 0;
			}

			//printf("Cも垂直\n");

			vector<COMPLEX> conv_A(2*SIZE),conv_B(2*SIZE);

			for(int i = 0; i < V[A].size(); i++){

				conv_A[loc[A][V[A][i]].y] += COUNT[A][V[A][i]];
			}
			for(int i = 0; i < V[B].size(); i++){

				conv_B[loc[B][V[B][i]].y] += COUNT[B][V[B][i]];
			}

			vector<COMPLEX> ret = convolution(conv_A,conv_B);

			ans = 0;
			for(int i = 0; i < V[C].size(); i++){

				ans += COUNT[C][V[C][i]]*(ll)round(ret[2*loc[C][V[C][i]].y].real());
			}

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

		}else{ //交点は高々1つなので、探す

			//printf("交点は高々1つ\n");

			vector<int> vec;

			for(ll y = 0; y <= 200000; y++){

				auto at = MAP[C].find(make_pair(X,y));
				if(at == MAP[C].end())continue;

				vec.push_back(at->second);
				//break;
			}

			if(vec.size() == 0){

				printf("0\n");
				return 0;
			}

			vector<COMPLEX> conv_A(2*SIZE),conv_B(2*SIZE);

			for(int i = 0; i < V[A].size(); i++){

				conv_A[loc[A][V[A][i]].y] += COUNT[A][V[A][i]];
			}
			for(int i = 0; i < V[B].size(); i++){

				conv_B[loc[B][V[B][i]].y] += COUNT[B][V[B][i]];
			}

			vector<COMPLEX> ret = convolution(conv_A,conv_B);

			ans = 0;
			for(int i = 0; i < vec.size(); i++){ //★★x_a+x_b == 2*x_c★★
				ans += COUNT[C][vec[i]]*(ll)round(ret[2*loc[C][vec[i]].y].real());
			}

			printf("%lld\n",ans);
		}

	}else{

		//printf("垂直でない平行\n");

		//AとBの中点を結んでできる直線のposを求める
		pos[C].slope = pos[A].slope;
		ll tmp_add_bunbo = 2*pos[A].add.denominator*pos[B].add.denominator;
		ll tmp_add_bunshi = pos[A].add.numerator*pos[B].add.denominator + pos[B].add.numerator*pos[A].add.denominator;


		ll work_1 = gcd(tmp_add_bunbo,tmp_add_bunshi);
		tmp_add_bunbo /= work_1;
		tmp_add_bunshi /= work_1;

		pos[C].add.denominator = tmp_add_bunbo;
		pos[C].add.numerator = tmp_add_bunshi;

		/*pos[A].debug();
		pos[B].debug();
		pos[C].debug();*/

		vector<int> vec;

		//中点をむすんで出来た直線の点を全探索
		for(ll x = 0; x <= 200000; x++){

			ll bunshi = pos[C].slope.numerator*pos[C].add.denominator*x + pos[C].slope.denominator*pos[C].add.numerator;
			ll bunbo = pos[C].slope.denominator*pos[C].add.denominator;

			if(bunshi%bunbo != 0)continue;

			ll tmp_y = bunshi/bunbo;

			auto at = MAP[C].find(make_pair(x,tmp_y));
			if(at == MAP[C].end())continue;

			vec.push_back(at->second);
		}

		vector<COMPLEX> conv_A(2*SIZE),conv_B(2*SIZE);

		for(int i = 0; i < V[A].size(); i++){

			conv_A[loc[A][V[A][i]].x] += COUNT[A][V[A][i]];
		}
		for(int i = 0; i < V[B].size(); i++){

			conv_B[loc[B][V[B][i]].x] += COUNT[B][V[B][i]];
		}

		vector<COMPLEX> ret = convolution(conv_A,conv_B);

		ans = 0;
		for(int i = 0; i < vec.size(); i++){

			ans += COUNT[C][vec[i]]*(ll)round(ret[2*loc[C][vec[i]].x].real());
		}

		printf("%lld\n",ans);
	}

	return 0;
}
accuracy: 1
time_ms: 460
memory_kb: 173196
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 200005
#define MAX 30

typedef complex<double> COMPLEX;



struct LOC{

	ll x,y;
};

struct Info{
	Info(int arg_left,int arg_right){
		left = arg_left;
		right = arg_right;
	}
	int left,right;
};

struct Info2{

	bool operator<(const struct Info2 &arg) const{

		return value < arg.value;
	}

	double value;
	ll num;
};

struct Data{
	void set(ll arg_denominator,ll arg_numerator){
        denominator = arg_denominator; //分母
        numerator = arg_numerator;
  	}
	ll denominator,numerator;
};

struct Pos{


	void debug(){

		printf("slope (%lld)/(%lld)  add (%lld)/(%lld)\n",slope.numerator,slope.denominator,add.numerator,add.denominator);
	}

	Data slope,add;
};


int LR_rev[2000005];
vector<Info> info;
vector<COMPLEX> conv_V[SIZE];
int POW[SIZE];

void calc_swap_pair(int N,int num_pow){

	LR_rev[0] = 0;

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

		if(i%2 == 1){

			LR_rev[i] = LR_rev[i-1]+POW[num_pow-1]; //1を足す代わりにPOW[num_pow-1]を足す

		}else{

			LR_rev[i] = LR_rev[i/2]/2; //半分のインデックスの値に、2を掛ける代わりに2で割る
		}

		if(i < LR_rev[i]){
			info.push_back(Info(i,LR_rev[i]));
		}
	}
}

void calc_COMPLEX(int N){

	for(int LEN = 2,num_pow = 0; LEN <= N; LEN *= 2,num_pow++){

		conv_V[num_pow].resize(LEN/2);

		conv_V[num_pow][0] = COMPLEX(cos(0),sin(0));

		COMPLEX mult = COMPLEX(cos((2*M_PI)/LEN),sin((2*M_PI)/LEN));

		for(int i = 1; i < LEN/2; i++){

			if(i%2 == 1){
				conv_V[num_pow][i] = conv_V[num_pow][i-1]*mult;
			}else{
				conv_V[num_pow][i] = conv_V[num_pow-1][i/2];
			}
		}
	}
}

//離散フーリエ変換
vector<COMPLEX> DFT(vector<COMPLEX> A) {

	int N = A.size();

	/*偶数項を左に、奇数項を右に仕分けるルールで要素数1まで仕分けした場合の、
	 * 最終結果を先に作っておく(ビットが左右反転したものがその位置に来る)*/
	for(int i = 0; i < info.size(); i++){

		swap(A[info[i].left],A[info[i].right]);
	}

	COMPLEX a,add;

	for(int LEN = 2,num_pow = 0; LEN <= N; LEN *= 2,num_pow++){

		for(int start = 0; start < N; start += LEN){
			for(int i = 0; i < LEN/2; i++){
				//マージソートの容量で、配列を更新していく
				a = A[start+i];
				add = conv_V[num_pow][i]*A[start+LEN/2+i];

				A[start+i] = a+add;
				A[start+LEN/2+i] = a-add;
			}
		}
	}
	return A;
}




//離散逆フーリエ変換
vector<COMPLEX> inverseDFT(vector<COMPLEX> A){

	int N = A.size();

	vector<COMPLEX> TMP = DFT(A);

	//係数を入れ替える&サイズNで各要素を割る
	vector<COMPLEX> RET(N);

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

		RET[i] = TMP[(N-i)%N];
		RET[i] = RET[i]/COMPLEX(N,0);
	}

	return RET;
}

vector<COMPLEX> convolution(vector<COMPLEX> A,vector<COMPLEX> B){

	int degree = (A.size()-1)+(B.size()-1)+1;

	int N = 1,num_pow = 0;
	while(N < degree){
		N *= 2;
		num_pow++;
	}

	info.clear();
	calc_swap_pair(N,num_pow);
	calc_COMPLEX(N);

	A.resize(N);
	B.resize(N);

	A = DFT(A);
	B = DFT(B);

	vector<COMPLEX> RET(N);

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

		RET[i] = A[i]*B[i];
	}

	return inverseDFT(RET);
}

//最大公約数
ll gcd(ll x,ll y){

	x = abs(x);
	y = abs(y);

	if(x < y){
		swap(x,y);
	}
	if(y == 0){
		return x;
	}else{
		return gcd(y,x%y);
	}
}

//最小公倍数
ll lcm(ll x,ll y){

	return (x*y)/gcd(x,y);
}


//傾きと切片を分数で計算して返却する関数
Pos calc_pos(LOC a,LOC b){

	Pos ret;

	if(a.x == b.x){ //垂直

		ret.slope.denominator = 1;
		ret.slope.numerator = BIG_NUM;

	}else if(a.y == b.y){ //水平

		ret.slope.denominator = 1;
		ret.slope.numerator = 0;
		ret.add.denominator = 1;
		ret.add.numerator = a.y;

	}else{

		//★符号に注意★
		ll diff_x = abs(a.x-b.x);
		ll diff_y = abs(a.y-b.y);
		ll common = gcd(diff_x,diff_y);
		diff_x /= common;
		diff_y /= common;

		ret.slope.denominator = diff_x;
		ret.slope.numerator = diff_y;

		if(((a.x-b.x) > 0 && (a.y-b.y) < 0) || ((a.x-b.x) < 0 && (a.y-b.y) > 0)){

			ret.slope.numerator *= -1;
			diff_y *= -1; //マイナスは分子につける
		}

		//printf("a:(%lld,%lld)\n",a.x,a.y);
		//printf("diff_x:%lld diff_y:%lld\n",diff_x,diff_y);

		ll tmp = a.y*diff_x-(diff_y*a.x);
		common = gcd(tmp,diff_x);

		diff_x /= common;
		tmp /= common;

		ret.add.denominator = diff_x;
		ret.add.numerator = tmp;
	}

	return ret;
}

bool is_Parallel(Pos a,Pos b){

	return a.slope.denominator == b.slope.denominator && a.slope.numerator == b.slope.numerator;
}


ll num[3];
ll num_point[3];
vector<int> V[3];
map<pair<ll,ll>,int> MAP[3]; //初出の座標のindexを保持するマップ
ll COUNT[3][SIZE];
ll add_X = 100000,add_Y = 100000;
int A=0,B=1,C=2;
LOC loc[3][SIZE];


int main(){

	POW[0] = 1;
	for(int i = 1; i < MAX; i++){

		POW[i] = POW[i-1]*2;
	}

	for(int i = 0; i < 3; i++){
		//座標の個数
		num_point[i] = 0;
	}
	for(int i = 0; i < 3; i++){
		for(int k = 0; k < SIZE; k++){
			COUNT[i][k] = 0; //同一の点をまとめる
		}
	}

	scanf("%lld %lld %lld",&num[A],&num[B],&num[C]);

	for(int loop = 0; loop < 3; loop++){
		for(int i = 0; i < num[loop]; i++){

			scanf("%lld %lld",&loc[loop][i].x,&loc[loop][i].y);
			loc[loop][i].x += add_X;
			loc[loop][i].y += add_Y;

			auto at = MAP[loop].find(make_pair(loc[loop][i].x,loc[loop][i].y));

			if(at == MAP[loop].end()){ //初めて出た座標

				MAP[loop][make_pair(loc[loop][i].x,loc[loop][i].y)] = i; //インデックスを記録

				V[loop].push_back(i);
				num_point[loop]++;
				COUNT[loop][i] = 1;

			}else{

				COUNT[loop][at->second]++;
			}
		}
	}

	ll ans;
	ll a_x,a_y,b_x,b_y,c_x,c_y;

	if((num_point[A] == 1)||(num_point[B] == 1)){ //AがBが1点の場合

		//printf("片方が1点\n");

		ans = 0;
		for(int i = 0; i < V[A].size(); i++){

			a_x = loc[A][V[A][i]].x;
			a_y = loc[A][V[A][i]].y;

			for(int k = 0; k < V[B].size(); k++){

				b_x = loc[B][V[B][k]].x;
				b_y = loc[B][V[B][k]].y;

				if((a_x+b_x)%2 == 1 || (a_y+b_y)%2 == 1)continue;

				c_x = (a_x+b_x)/2;
				c_y = (a_y+b_y)/2;

				auto at = MAP[C].find(make_pair(c_x,c_y));
				if(at == MAP[C].end())continue;

				ans += COUNT[A][V[A][i]]*COUNT[B][V[B][k]]*COUNT[C][at->second];
			}
		}

		printf("%lld\n",ans);
		return 0;
	}

	//AとBの傾きを計算
	Pos pos[3];

	pos[A] = calc_pos(loc[A][V[A][0]],loc[A][V[A][1]]);
	pos[B] = calc_pos(loc[B][V[B][0]],loc[B][V[B][1]]);

	//return 0;

	double slope_A = (double)pos[A].slope.numerator/(double)pos[A].slope.denominator;
	double add_A = (double)pos[A].add.numerator/(double)pos[A].add.denominator;

	double slope_B = (double)pos[B].slope.numerator/(double)pos[B].slope.denominator;
	double add_B = (double)pos[B].add.numerator/(double)pos[B].add.denominator;

	double d_x_a,d_x_b,d_x_c,d_y_a,d_y_c;

	if(!is_Parallel(pos[A],pos[B])){ //AとBが平行でない場合

		//printf("AとBが平行でない\n");

		if(pos[B].slope.numerator == BIG_NUM){ //Bが垂直

			swap(A,B); //Aを垂直にする
			swap(slope_A,slope_B);
			swap(add_A,add_B);
		}

		//整数のまま演算すると桁あふれするので実数でやる
		vector<Info2> info_A,info_B;
		vector<double> v_A,v_B;

		for(int i = 0; i < V[A].size(); i++){
			Info2 tmp_info;
			if(pos[A].slope.numerator == BIG_NUM){ //Aが垂直

				tmp_info.value = loc[A][V[A][i]].y; //垂直ならy座標

			}else{

				tmp_info.value = loc[A][V[A][i]].x; //垂直でないならx座標
			}
			v_A.push_back(tmp_info.value);
			tmp_info.num = COUNT[A][V[A][i]]; //重み
			info_A.push_back(tmp_info);
		}
		sort(info_A.begin(),info_A.end());
		sort(v_A.begin(),v_A.end());

		for(int i = 0; i < V[B].size(); i++){
			Info2 tmp_info;
			tmp_info.value = loc[B][V[B][i]].x; //座標
			tmp_info.num = COUNT[B][V[B][i]]; //重み
			v_B.push_back(tmp_info.value);
			info_B.push_back(tmp_info);
		}
		sort(info_B.begin(),info_B.end());
		sort(v_B.begin(),v_B.end());

		ans = 0;

		//Cの座標からA,Bの座標を計算する
		for(int i = 0; i < V[C].size(); i++){

			d_x_c = loc[C][V[C][i]].x;
			d_y_c = loc[C][V[C][i]].y;

			if(pos[A].slope.numerator == BIG_NUM){ //Aが垂直

				d_x_a = loc[A][V[A][0]].x;
				d_x_b = 2*d_x_c-d_x_a;
				d_y_a = 2*d_y_c-(slope_B*d_x_b+add_B);

			}else{ //Aが垂直ではない

				d_x_a = (2*d_y_c-(add_A+2*slope_B*d_x_c+add_B))/(slope_A-slope_B);
				d_x_b = 2*d_x_c-(d_x_a);
			}

			int at_a;

			if(pos[A].slope.numerator == BIG_NUM){ //Aが垂直

				at_a = lower_bound(v_A.begin(),v_A.end(),d_y_a-EPS)-v_A.begin();
				if(at_a == v_A.size() || fabs(d_y_a-info_A[at_a].value) >= EPS)continue;

			}else{

				at_a = lower_bound(v_A.begin(),v_A.end(),d_x_a-EPS)-v_A.begin();
				if(at_a == v_A.size() || fabs(d_x_a-info_A[at_a].value) >= EPS)continue;
			}

			int at_b = lower_bound(v_B.begin(),v_B.end(),d_x_b-EPS)-v_B.begin();
			if(at_b == v_B.size() || fabs(d_x_b-info_B[at_b].value) >= EPS)continue;

			ans += info_A[at_a].num*info_B[at_b].num*COUNT[C][V[C][i]];
		}

		printf("%lld\n",ans);
		return 0;
	}

	//AとBが平行である場合
	//Cが(AとBの中点を結んだ直線上)にあるか否かで場合分け
	//printf("AとBが平行\n");

	if(pos[A].slope.numerator == BIG_NUM && pos[B].slope.numerator == BIG_NUM){ //両方垂直

		if((loc[A][V[A][0]].x+loc[B][V[B][0]].x)%2 == 1){

			printf("0\n");
			return 0;
		}

		ll X = (loc[A][V[A][0]].x+loc[B][V[B][0]].x)/2;

		if(num_point[C] == 1){ //Cが1点だけ

			if(loc[C][V[C][0]].x != X){

				printf("0\n");
				return 0;
			}

			pos[C].slope.denominator = 1;
			pos[C].slope.numerator = BIG_NUM;

		}else{ //Cが2点以上

			pos[C] = calc_pos(loc[C][V[C][0]],loc[C][V[C][1]]);
		}

		if(pos[C].slope.numerator == BIG_NUM){ //Cも垂直

			if(loc[C][V[C][0]].x != X){

				printf("0\n");
				return 0;
			}

			//printf("Cも垂直\n");

			vector<COMPLEX> conv_A(2*SIZE),conv_B(2*SIZE);

			for(int i = 0; i < V[A].size(); i++){

				conv_A[loc[A][V[A][i]].y] += COUNT[A][V[A][i]];
			}
			for(int i = 0; i < V[B].size(); i++){

				conv_B[loc[B][V[B][i]].y] += COUNT[B][V[B][i]];
			}

			vector<COMPLEX> ret = convolution(conv_A,conv_B);

			ans = 0;
			for(int i = 0; i < V[C].size(); i++){

				ans += COUNT[C][V[C][i]]*(ll)round(ret[loc[C][V[C][i]].y].real());
			}

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

		}else{ //交点は高々1つなので、探す

			//printf("交点は高々1つ\n");

			vector<int> vec;

			for(ll y = 0; y <= 200000; y++){

				auto at = MAP[C].find(make_pair(X,y));
				if(at == MAP[C].end())continue;

				vec.push_back(at->second);
				//break;
			}

			if(vec.size() == 0){

				printf("0\n");
				return 0;
			}

			vector<COMPLEX> conv_A(2*SIZE),conv_B(2*SIZE);

			for(int i = 0; i < V[A].size(); i++){

				conv_A[loc[A][V[A][i]].y] += COUNT[A][V[A][i]];
			}
			for(int i = 0; i < V[B].size(); i++){

				conv_B[loc[B][V[B][i]].y] += COUNT[B][V[B][i]];
			}

			vector<COMPLEX> ret = convolution(conv_A,conv_B);

			ans = 0;
			for(int i = 0; i < vec.size(); i++){ //★★x_a+x_b == 2*x_c★★
				ans += COUNT[C][vec[i]]*(ll)round(ret[2*loc[C][vec[i]].y].real());
			}

			printf("%lld\n",ans);
		}

	}else{

		//printf("垂直でない平行\n");

		//AとBの中点を結んでできる直線のposを求める
		pos[C].slope = pos[A].slope;
		ll tmp_add_bunbo = 2*pos[A].add.denominator*pos[B].add.denominator;
		ll tmp_add_bunshi = pos[A].add.numerator*pos[B].add.denominator + pos[B].add.numerator*pos[A].add.denominator;


		ll work_1 = gcd(tmp_add_bunbo,tmp_add_bunshi);
		tmp_add_bunbo /= work_1;
		tmp_add_bunshi /= work_1;

		pos[C].add.denominator = tmp_add_bunbo;
		pos[C].add.numerator = tmp_add_bunshi;

		/*pos[A].debug();
		pos[B].debug();
		pos[C].debug();*/

		vector<int> vec;

		//中点をむすんで出来た直線の点を全探索
		for(ll x = 0; x <= 200000; x++){

			ll bunshi = pos[C].slope.numerator*pos[C].add.denominator*x + pos[C].slope.denominator*pos[C].add.numerator;
			ll bunbo = pos[C].slope.denominator*pos[C].add.denominator;

			if(bunshi%bunbo != 0)continue;

			ll tmp_y = bunshi/bunbo;

			auto at = MAP[C].find(make_pair(x,tmp_y));
			if(at == MAP[C].end())continue;

			vec.push_back(at->second);
		}

		vector<COMPLEX> conv_A(2*SIZE),conv_B(2*SIZE);

		for(int i = 0; i < V[A].size(); i++){

			conv_A[loc[A][V[A][i]].x] += COUNT[A][V[A][i]];
		}
		for(int i = 0; i < V[B].size(); i++){

			conv_B[loc[B][V[B][i]].x] += COUNT[B][V[B][i]];
		}

		vector<COMPLEX> ret = convolution(conv_A,conv_B);

		ans = 0;
		for(int i = 0; i < vec.size(); i++){

			ans += COUNT[C][vec[i]]*(ll)round(ret[2*loc[C][vec[i]].x].real());
		}

		printf("%lld\n",ans);
	}

	return 0;
}
accuracy: 0.3728813559322034
time_ms: 280
memory_kb: 148144
final_rank: 15

code_snippet: #include <bits/stdc++.h>
using namespace std;
using lld = int64_t;
using I128 = __int128;
typedef long long ll;
using pII = pair<I128,I128>;
using pll = pair<ll,ll>;
typedef pair<int,int> pii;
typedef pair<double,double> pdd;
typedef complex<double> cplex;
const double pi=acos(-1);
const int INF = 500000;
const int N = 100000 + 5;

int l, m, n;

pair< int, int > a[ N ], b[ N ], c[ N ];

void init() {
	cin >> l >> m >> n;
	for ( int i = 0 ; i < l ; ++ i )
		cin >> a[ i ].first >> a[ i ].second;
	for ( int i = 0 ; i < m ; ++ i )
		cin >> b[ i ].first >> b[ i ].second;
	for ( int i = 0 ; i < n ; ++ i )
		cin >> c[ i ].first >> c[ i ].second;
}

void solve_brute() {
	map< pair< int, int >, lld > cntA, cntB;
	for ( int i = 0 ; i < l ; ++ i )
		cntA[ a[ i ] ] ++;
	for ( int i = 0 ; i < m ; ++ i )
		cntB[ b[ i ] ] ++;

	lld ans = 0;

	lld a0x = a[ 0 ].first, a0y = a[ 0 ].second;
	lld b0x = b[ 0 ].first, b0y = b[ 0 ].second;
	lld dax = a[ 1 ].first - a[ 0 ].first;
	lld day = a[ 1 ].second - a[ 0 ].second;
	lld dbx = b[ 1 ].first - b[ 0 ].first;
	lld dby = b[ 1 ].second - b[ 0 ].second;

	for ( int i = 0 ; i < n ; ++ i ) {
		lld cx = 2 * c[ i ].first, cy = 2 * c[ i ].second;
		cx -= a0x + b0x;
		cy -= a0y + b0y;

		lld det = dax * dby - dbx * day;
		lld ma = cx * dby - cy * dbx;
		lld mb = cy * dax - cx * day; 

		// cout << "MA = " << ma << '\n';
		// cout << "MB = " << mb << '\n';
		// cout << "DAX = " << dax <<'\n';
		// cout << "DAY = " << day << '\n';
		// cout << "DBX = " << dbx << '\n';
		// cout << "DBY = " << dby << '\n';
		// cout << "DET = " << det << '\n';

		if ( ( ma * dax ) % det != 0 ) continue;
		if ( ( ma * day ) % det != 0 ) continue;
		if ( ( mb * dbx ) % det != 0 ) continue;
		if ( ( mb * dby ) % det != 0 ) continue;

		// cout << "JIZZ\n";

		lld ax = a0x + ma * dax / det, ay = a0y + ma * day / det;
		lld bx = b0x + mb * dbx / det, by = b0y + mb * dby / det;

		ans += cntA[ { ax, ay } ] * cntB[ { bx, by } ];
	}
	cout << ans << '\n';
}

map<pair<int,int>,int> adic,bdic,cdic;
inline ll cross(pll o,pll a,pll b){
	return (a.first-o.first)*(b.second-o.second)-(a.second-o.second)*(b.first-o.first);
}
inline ll cross(pll v1,pll v2,pll v3,pll v4){
	return (v2.first-v1.first)*(v4.second-v3.second)-(v2.second-v1.second)*(v4.first-v3.first);
}

using wtf = pair< pII, pII >;

inline wtf get_point(pll v1,pll v2,pll v3,pll v4){
	ll a1=cross(v3,v1,v4),a2=cross(v3,v4,v2);
	// cout<<"a1="<<a1<<",a2="<<a2<<'\n';
	// double x=(double)(v1.first*a2+v2.first*a1)/(a1+a2);
	// double y=(double)(v1.second*a2+v2.second*a1)/(a1+a2);
	return wtf( {(v1.first*a2+v2.first*a1), (a1+a2)}, {(v1.second*a2+v2.second*a1),(a1+a2)} );
}
inline double dist(pii v1,pii v2){
	return sqrt((ll)(v1.first-v2.first)*(v1.first-v2.first)+(ll)(v1.second-v2.second)*(v1.second-v2.second));
}
inline int rev_bit(int bit,int len){
	int rev=0;
	for(int i=0;(1<<i)<len;i++){
		rev<<=1;
		if((1<<i)&bit) rev|=1;
	}
	return rev;
}
bool fin[1200040];
void exec_fft(cplex* f,int len,int o){
	for(int i=0;i<len;i++) fin[i]=false;
	for(int i=0;i<len;i++){
		if(!fin[i]){
			int rev=rev_bit(i,len);
			fin[rev]=fin[i]=true;
			swap(f[rev],f[i]);
		}
	}
	for(int s=2;s<=len;s<<=1){
		cplex mul=cplex(cos(2*pi*o/s),sin(2*pi*o/s));
		for(int j=0;j<len;j+=s){
			cplex e=cplex(1,0);
			for(int k=0;k<(s>>1);k++){
				cplex t=f[j+k+(s>>1)]*e;
				cplex u=f[j+k];
				f[j+k]=u+t;
				f[j+k+(s>>1)]=u-t;
				e*=mul;
			}
		}
	}
	if(o==-1){
		for(int i=0;i<len;i++)
			f[i]/=(double)len;
	}
}
cplex f[1200040],g[1200040];
ll solve_pp(){

	if(cross(a[0],a[1],c[0],c[1])==0){
		// cout<<"WTFFF\n";
		double d1=abs(cross(a[0],c[0],c[1]))/dist(c[0],c[1]);
		double d2=abs(cross(b[0],c[0],c[1]))/dist(c[0],c[1]);
		if(abs(d1-d2)<1e-10){
			// cout << "JIZZ\n";

			if ( a[ 0 ].first != a[ 1 ].first ) {

				for(int i=0;i<l;i++)
					f[a[i].first+100000]=cplex(f[a[i].first+100000].real()+1,0);
				for(int i=0;i<m;i++)
					g[b[i].first+100000]=cplex(g[b[i].first+100000].real()+1,0);
				int sz=1;
				while(sz<=(400005)) sz<<=1;
				exec_fft(f,sz,1);
				exec_fft(g,sz,1);
				for(int i=0;i<sz;i++)
					f[i]*=g[i];
				exec_fft(f,sz,-1);
				ll ret=0;

				// for ( int i = 0 ; i < sz ; ++ i ) {
				// 	if ( static_cast< int >( floor(f[i].real()+0.3) ) ) {
				// 		cout << i << " meow\n";
				// 	}
				// }

				for(int i=0;i<n;i++){
					ret+=floor(f[c[i].first*2+200000].real()+0.3);
				}
				return ret;
			} else {
				for(int i=0;i<l;i++)
					f[a[i].second+100000]=cplex(f[a[i].second+100000].real()+1,0);
				for(int i=0;i<m;i++)
					g[b[i].second+100000]=cplex(g[b[i].second+100000].real()+1,0);
				int sz=1;
				while(sz<=(400005)) sz<<=1;
				exec_fft(f,sz,1);
				exec_fft(g,sz,1);
				for(int i=0;i<sz;i++)
					f[i]*=g[i];
				exec_fft(f,sz,-1);
				ll ret=0;

				// for ( int i = 0 ; i < sz ; ++ i ) {
				// 	if ( static_cast< int >( floor(f[i].real()+0.3) ) ) {
				// 		cout << i << " meow\n";
				// 	}
				// }

				for(int i=0;i<n;i++){
					ret+=floor(f[c[i].second*2+200000].real()+0.3);
				}
				return ret;
			}
		}else{
			return 0;
		}
	}else{
		// cout << "Obov\n";
		wtf x=get_point(a[0],a[1],c[0],c[1]);
		wtf y=get_point(b[0],b[1],c[0],c[1]);

		// cout << "("<<x.first.first<<"/"<<x.first.second<<","<<x.second.first<<"/"<<x.second.second<<")\n";
		// cout << "("<<y.first.first<<"/"<<y.first.second<<","<<y.second.first<<"/"<<y.second.second<<")\n";

		wtf z = wtf(
		{
			x.first.first*y.first.second+y.first.first*x.first.second,
			x.first.second*y.first.second
		},
		{
			x.second.first*y.second.second+x.second.second*y.second.first,
			x.second.second*y.second.second
		} );

		// pdd z=pdd((x.first+y.first),(x.second+y.second));
		for(int i=0;i<l;i++)
			adic[a[i]]++;
		for(int i=0;i<m;i++)
			bdic[b[i]]++;
		for(int i=0;i<n;i++)
			cdic[c[i]]++;
		ll ret=0;
		for(auto it=adic.begin();it!=adic.end();it++) {

			if ( ( z.first.first - it->first.first * z.first.second ) % z.first.second )
				continue;
			if ( ( z.second.first - it->first.second * z.second.second ) % z.second.second )
				continue;

			ret+=(ll)it->second*bdic[{ static_cast<lld>( z.first.first - it->first.first * z.first.second ) / z.first.second, static_cast<lld>( z.second.first - it->first.second * z.second.second ) / z.second.second }];
		}
		return ret;
	}
}

void solve_pin() {
	// cout << "MEOW\n";
	cout << solve_pp() << '\n';
}

void solve() {

	sort( a, a + l );
	sort( b, b + m );
	sort( c, c + m );

	if ( a[ l - 1 ] == a[ 0 ] and b[ m - 1 ] == b[ 0 ] ) {
		map< pair< int, int >, int > cnt;
		for ( int i = 0 ; i < n ; ++ i )
			cnt[ c[ i ] ]++;
		int dx = ( a[ 0 ].first + b[ 0 ].first );
		int dy = ( a[ 0 ].second + b[ 0 ].second );
		if ( ( dx & 1 ) or ( dy & 1 ) ) {
			cout << 0 << '\n';
		} else {
			dx >>= 1, dy >>= 1;
			cout << static_cast< lld >( cnt[ { dx, dy } ] ) * l * m << '\n';
		}
		return;
	} else if ( b[ m - 1 ] == b[ 0 ] and c[ n - 1 ] == c[ 0 ] ) {
		map< pair< int, int >, int > cnt;
		for ( int i = 0 ; i < l ; ++ i )
			cnt[ a[ i ] ]++;
		int dx = 2 * c[ 0 ].first - b[ 0 ].first;
		int dy = 2 * c[ 0 ].second - b[ 0 ].second;
		cout << static_cast< int >( cnt[ { dx, dy } ] ) * m * n << '\n';
		return;
	} else if ( c[ n - 1 ] == c[ 0 ] and a[ l - 1 ] == a[ 0 ] ) {
		map< pair< int, int >, int > cnt;
		for ( int i = 0 ; i < m ; ++ i )
			cnt[ b[ i ] ]++;
		int dx = 2 * c[ 0 ].first - a[ 0 ].first;
		int dy = 2 * c[ 0 ].second - a[ 0 ].second;
		cout << static_cast< int >( cnt[ { dx, dy } ] ) * n * l << '\n';
		return;
	}

	if ( a[ l - 1 ] == a[ 0 ] ) {
		a[ l ++ ] = { INF, INF };
	} else if ( b[ m - 1 ] == b[ 0 ] ) {
		b[ m ++ ] = { INF, INF };
	} else if ( c[ n - 1 ] == c[ 0 ] ) {
		c[ n ++ ] = { INF, INF };
	}

	swap( a[ 1 ], a[ l - 1 ] );
	swap( b[ 1 ], b[ m - 1 ] );
	swap( c[ 1 ], c[ n - 1 ] );


	const lld ax = ( a[ 0 ].first - a[ 1 ].first );
	const lld ay = ( a[ 0 ].second - a[ 1 ].second );

	const lld bx = ( b[ 0 ].first - b[ 1 ].first );
	const lld by = ( b[ 0 ].second - b[ 1 ].second );

	if ( ax * by - bx * ay == 0 ) {
		solve_pin();
	} else {
		solve_brute();
	}
}

int main() {
	ios_base::sync_with_stdio( false );
	cin.tie( nullptr );
	init(); solve();
	return 0;
}
accuracy: 1
time_ms: 210
memory_kb: 22816
final_rank: 2

code_snippet: #include <bits/stdc++.h>
using namespace std;
using lld = int64_t;
typedef long long ll;
using pll = pair<ll,ll>;
typedef pair<int,int> pii;
typedef pair<double,double> pdd;
typedef complex<double> cplex;
const double pi=acos(-1);
const int INF = 500000;
const int N = 100000 + 5;

int l, m, n;

pair< int, int > a[ N ], b[ N ], c[ N ];

void init() {
	cin >> l >> m >> n;
	for ( int i = 0 ; i < l ; ++ i )
		cin >> a[ i ].first >> a[ i ].second;
	for ( int i = 0 ; i < m ; ++ i )
		cin >> b[ i ].first >> b[ i ].second;
	for ( int i = 0 ; i < n ; ++ i )
		cin >> c[ i ].first >> c[ i ].second;
}

void solve_brute() {
	map< pair< int, int >, lld > cntA, cntB;
	for ( int i = 0 ; i < l ; ++ i )
		cntA[ a[ i ] ] ++;
	for ( int i = 0 ; i < m ; ++ i )
		cntB[ b[ i ] ] ++;

	lld ans = 0;

	lld a0x = a[ 0 ].first, a0y = a[ 0 ].second;
	lld b0x = b[ 0 ].first, b0y = b[ 0 ].second;
	lld dax = a[ 1 ].first - a[ 0 ].first;
	lld day = a[ 1 ].second - a[ 0 ].second;
	lld dbx = b[ 1 ].first - b[ 0 ].first;
	lld dby = b[ 1 ].second - b[ 0 ].second;

	for ( int i = 0 ; i < n ; ++ i ) {
		lld cx = 2 * c[ i ].first, cy = 2 * c[ i ].second;
		cx -= a0x + b0x;
		cy -= a0y + b0y;

		lld det = dax * dby - dbx * day;
		lld ma = cx * dby - cy * dbx;
		lld mb = cy * dax - cx * day; 

		// cout << "MA = " << ma << '\n';
		// cout << "MB = " << mb << '\n';
		// cout << "DAX = " << dax <<'\n';
		// cout << "DAY = " << day << '\n';
		// cout << "DBX = " << dbx << '\n';
		// cout << "DBY = " << dby << '\n';
		// cout << "DET = " << det << '\n';

		if ( ( ma * dax ) % det != 0 ) continue;
		if ( ( ma * day ) % det != 0 ) continue;
		if ( ( mb * dbx ) % det != 0 ) continue;
		if ( ( mb * dby ) % det != 0 ) continue;

		// cout << "JIZZ\n";

		lld ax = a0x + ma * dax / det, ay = a0y + ma * day / det;
		lld bx = b0x + mb * dbx / det, by = b0y + mb * dby / det;

		ans += cntA[ { ax, ay } ] * cntB[ { bx, by } ];
	}
	cout << ans << '\n';
}

map<pair<int,int>,int> adic,bdic,cdic;
inline ll cross(pll o,pll a,pll b){
	return (a.first-o.first)*(b.second-o.second)-(a.second-o.second)*(b.first-o.first);
}
inline ll cross(pll v1,pll v2,pll v3,pll v4){
	return (v2.first-v1.first)*(v4.second-v3.second)-(v2.second-v1.second)*(v4.first-v3.first);
}

using wtf = pair< pll, pll >;

inline wtf get_point(pll v1,pll v2,pll v3,pll v4){
	ll a1=cross(v3,v1,v4),a2=cross(v3,v4,v2);
	// cout<<"a1="<<a1<<",a2="<<a2<<'\n';
	// double x=(double)(v1.first*a2+v2.first*a1)/(a1+a2);
	// double y=(double)(v1.second*a2+v2.second*a1)/(a1+a2);
	return wtf( {(v1.first*a2+v2.first*a1), (a1+a2)}, {(v1.second*a2+v2.second*a1),(a1+a2)} );
}
inline double dist(pii v1,pii v2){
	return sqrt((ll)(v1.first-v2.first)*(v1.first-v2.first)+(ll)(v1.second-v2.second)*(v1.second-v2.second));
}
inline int rev_bit(int bit,int len){
	int rev=0;
	for(int i=0;(1<<i)<len;i++){
		rev<<=1;
		if((1<<i)&bit) rev|=1;
	}
	return rev;
}
bool fin[1200040];
void exec_fft(cplex* f,int len,int o){
	for(int i=0;i<len;i++) fin[i]=false;
	for(int i=0;i<len;i++){
		if(!fin[i]){
			int rev=rev_bit(i,len);
			fin[rev]=fin[i]=true;
			swap(f[rev],f[i]);
		}
	}
	for(int s=2;s<=len;s<<=1){
		cplex mul=cplex(cos(2*pi*o/s),sin(2*pi*o/s));
		for(int j=0;j<len;j+=s){
			cplex e=cplex(1,0);
			for(int k=0;k<(s>>1);k++){
				cplex t=f[j+k+(s>>1)]*e;
				cplex u=f[j+k];
				f[j+k]=u+t;
				f[j+k+(s>>1)]=u-t;
				e*=mul;
			}
		}
	}
	if(o==-1){
		for(int i=0;i<len;i++)
			f[i]/=(double)len;
	}
}
cplex f[1200040],g[1200040];
ll solve_pp(){

	if(cross(a[0],a[1],c[0],c[1])==0){
		// cout<<"WTFFF\n";
		double d1=abs(cross(a[0],c[0],c[1]))/dist(c[0],c[1]);
		double d2=abs(cross(b[0],c[0],c[1]))/dist(c[0],c[1]);
		if(abs(d1-d2)<1e-10){
			// cout << "JIZZ\n";

			if ( a[ 0 ].first != a[ 1 ].first ) {

				for(int i=0;i<l;i++)
					f[a[i].first+100000]=cplex(f[a[i].first+100000].real()+1,0);
				for(int i=0;i<m;i++)
					g[b[i].first+100000]=cplex(g[b[i].first+100000].real()+1,0);
				int sz=1;
				while(sz<=(400005)) sz<<=1;
				exec_fft(f,sz,1);
				exec_fft(g,sz,1);
				for(int i=0;i<sz;i++)
					f[i]*=g[i];
				exec_fft(f,sz,-1);
				ll ret=0;

				// for ( int i = 0 ; i < sz ; ++ i ) {
				// 	if ( static_cast< int >( floor(f[i].real()+0.3) ) ) {
				// 		cout << i << " meow\n";
				// 	}
				// }

				for(int i=0;i<n;i++){
					ret+=floor(f[c[i].first*2+200000].real()+0.3);
				}
				return ret;
			} else {
				for(int i=0;i<l;i++)
					f[a[i].second+100000]=cplex(f[a[i].second+100000].real()+1,0);
				for(int i=0;i<m;i++)
					g[b[i].second+100000]=cplex(g[b[i].second+100000].real()+1,0);
				int sz=1;
				while(sz<=(400005)) sz<<=1;
				exec_fft(f,sz,1);
				exec_fft(g,sz,1);
				for(int i=0;i<sz;i++)
					f[i]*=g[i];
				exec_fft(f,sz,-1);
				ll ret=0;

				// for ( int i = 0 ; i < sz ; ++ i ) {
				// 	if ( static_cast< int >( floor(f[i].real()+0.3) ) ) {
				// 		cout << i << " meow\n";
				// 	}
				// }

				for(int i=0;i<n;i++){
					ret+=floor(f[c[i].second*2+200000].real()+0.3);
				}
				return ret;
			}
		}else{
			return 0;
		}
	}else{
		cout << "Obov\n";
		wtf x=get_point(a[0],a[1],c[0],c[1]);
		wtf y=get_point(b[0],b[1],c[0],c[1]);

		// cout << "("<<x.first.first<<"/"<<x.first.second<<","<<x.second.first<<"/"<<x.second.second<<")\n";
		// cout << "("<<y.first.first<<"/"<<y.first.second<<","<<y.second.first<<"/"<<y.second.second<<")\n";

		wtf z = wtf(
		{
			x.first.first*y.first.second+y.first.first*x.first.second,
			x.first.second*y.first.second
		},
		{
			x.second.first*y.second.second+x.second.second*y.second.first,
			x.second.second*y.second.second
		} );

		// pdd z=pdd((x.first+y.first),(x.second+y.second));
		for(int i=0;i<l;i++)
			adic[a[i]]++;
		for(int i=0;i<m;i++)
			bdic[b[i]]++;
		for(int i=0;i<n;i++)
			cdic[c[i]]++;
		ll ret=0;
		for(auto it=adic.begin();it!=adic.end();it++) {

			if ( ( z.first.first - it->first.first * z.first.second ) % z.first.second )
				continue;
			if ( ( z.second.first - it->first.second * z.second.second ) % z.second.second )
				continue;

			ret+=(ll)it->second*bdic[{ ( z.first.first - it->first.first * z.first.second ) / z.first.second, ( z.second.first - it->first.second * z.second.second ) / z.second.second }];
		}
		return ret;
	}
}

void solve_pin() {
	// cout << "MEOW\n";
	cout << solve_pp() << '\n';
}

void solve() {

	sort( a, a + l );
	sort( b, b + m );
	sort( c, c + m );

	if ( a[ l - 1 ] == a[ 0 ] and b[ m - 1 ] == b[ 0 ] ) {
		map< pair< int, int >, int > cnt;
		for ( int i = 0 ; i < n ; ++ i )
			cnt[ c[ i ] ]++;
		int dx = ( a[ 0 ].first + b[ 0 ].first );
		int dy = ( a[ 0 ].second + b[ 0 ].second );
		if ( ( dx & 1 ) or ( dy & 1 ) ) {
			cout << 0 << '\n';
		} else {
			dx >>= 1, dy >>= 1;
			cout << static_cast< lld >( cnt[ { dx, dy } ] ) * l * m << '\n';
		}
		return;
	} else if ( b[ m - 1 ] == b[ 0 ] and c[ n - 1 ] == c[ 0 ] ) {
		map< pair< int, int >, int > cnt;
		for ( int i = 0 ; i < l ; ++ i )
			cnt[ a[ i ] ]++;
		int dx = 2 * c[ 0 ].first - b[ 0 ].first;
		int dy = 2 * c[ 0 ].second - b[ 0 ].second;
		cout << static_cast< int >( cnt[ { dx, dy } ] ) * m * n << '\n';
		return;
	} else if ( c[ n - 1 ] == c[ 0 ] and a[ l - 1 ] == a[ 0 ] ) {
		map< pair< int, int >, int > cnt;
		for ( int i = 0 ; i < m ; ++ i )
			cnt[ b[ i ] ]++;
		int dx = 2 * c[ 0 ].first - a[ 0 ].first;
		int dy = 2 * c[ 0 ].second - a[ 0 ].second;
		cout << static_cast< int >( cnt[ { dx, dy } ] ) * n * l << '\n';
		return;
	}

	if ( a[ l - 1 ] == a[ 0 ] ) {
		a[ l ++ ] = { INF, INF };
	} else if ( b[ m - 1 ] == b[ 0 ] ) {
		b[ m ++ ] = { INF, INF };
	} else if ( c[ n - 1 ] == c[ 0 ] ) {
		c[ n ++ ] = { INF, INF };
	}

	swap( a[ 1 ], a[ l - 1 ] );
	swap( b[ 1 ], b[ m - 1 ] );
	swap( c[ 1 ], c[ n - 1 ] );


	const lld ax = ( a[ 0 ].first - a[ 1 ].first );
	const lld ay = ( a[ 0 ].second - a[ 1 ].second );

	const lld bx = ( b[ 0 ].first - b[ 1 ].first );
	const lld by = ( b[ 0 ].second - b[ 1 ].second );

	if ( ax * by - bx * ay == 0 ) {
		solve_pin();
	} else {
		solve_brute();
	}
}

int main() {
	ios_base::sync_with_stdio( false );
	cin.tie( nullptr );
	init(); solve();
	return 0;
}
accuracy: 0.9661016949152542
time_ms: 200
memory_kb: 22844
final_rank: 8

code_snippet: #include <bits/stdc++.h>
using namespace std;
using lld = int64_t;
typedef long long ll;
using pll = pair<ll,ll>;
typedef pair<int,int> pii;
typedef pair<double,double> pdd;
typedef complex<double> cplex;
const double pi=acos(-1);
const int INF = 500000;
const int N = 100000 + 5;

int l, m, n;

pair< int, int > a[ N ], b[ N ], c[ N ];

void init() {
	cin >> l >> m >> n;
	for ( int i = 0 ; i < l ; ++ i )
		cin >> a[ i ].first >> a[ i ].second;
	for ( int i = 0 ; i < m ; ++ i )
		cin >> b[ i ].first >> b[ i ].second;
	for ( int i = 0 ; i < n ; ++ i )
		cin >> c[ i ].first >> c[ i ].second;
}

void solve_brute() {
	map< pair< int, int >, lld > cntA, cntB;
	for ( int i = 0 ; i < l ; ++ i )
		cntA[ a[ i ] ] ++;
	for ( int i = 0 ; i < m ; ++ i )
		cntB[ b[ i ] ] ++;

	lld ans = 0;

	lld a0x = a[ 0 ].first, a0y = a[ 0 ].second;
	lld b0x = b[ 0 ].first, b0y = b[ 0 ].second;
	lld dax = a[ 1 ].first - a[ 0 ].first;
	lld day = a[ 1 ].second - a[ 0 ].second;
	lld dbx = b[ 1 ].first - b[ 0 ].first;
	lld dby = b[ 1 ].second - b[ 0 ].second;

	for ( int i = 0 ; i < n ; ++ i ) {
		lld cx = 2 * c[ i ].first, cy = 2 * c[ i ].second;
		cx -= a0x + b0x;
		cy -= a0y + b0y;

		lld det = dax * dby - dbx * day;
		lld ma = cx * dby - cy * dbx;
		lld mb = cy * dax - cx * day; 

		// cout << "MA = " << ma << '\n';
		// cout << "MB = " << mb << '\n';
		// cout << "DAX = " << dax <<'\n';
		// cout << "DAY = " << day << '\n';
		// cout << "DBX = " << dbx << '\n';
		// cout << "DBY = " << dby << '\n';
		// cout << "DET = " << det << '\n';

		if ( ( ma * dax ) % det != 0 ) continue;
		if ( ( ma * day ) % det != 0 ) continue;
		if ( ( mb * dbx ) % det != 0 ) continue;
		if ( ( mb * dby ) % det != 0 ) continue;

		// cout << "JIZZ\n";

		lld ax = a0x + ma * dax / det, ay = a0y + ma * day / det;
		lld bx = b0x + mb * dbx / det, by = b0y + mb * dby / det;

		ans += cntA[ { ax, ay } ] * cntB[ { bx, by } ];
	}
	cout << ans << '\n';
}

map<pair<int,int>,int> adic,bdic,cdic;
inline ll cross(pll o,pll a,pll b){
	return (a.first-o.first)*(b.second-o.second)-(a.second-o.second)*(b.first-o.first);
}
inline ll cross(pll v1,pll v2,pll v3,pll v4){
	return (v2.first-v1.first)*(v4.second-v3.second)-(v2.second-v1.second)*(v4.first-v3.first);
}

using wtf = pair< pll, pll >;

inline wtf get_point(pll v1,pll v2,pll v3,pll v4){
	ll a1=cross(v3,v1,v4),a2=cross(v3,v4,v2);
	// cout<<"a1="<<a1<<",a2="<<a2<<'\n';
	// double x=(double)(v1.first*a2+v2.first*a1)/(a1+a2);
	// double y=(double)(v1.second*a2+v2.second*a1)/(a1+a2);
	return wtf( {(v1.first*a2+v2.first*a1), (a1+a2)}, {(v1.second*a2+v2.second*a1),(a1+a2)} );
}
inline double dist(pii v1,pii v2){
	return sqrt((ll)(v1.first-v2.first)*(v1.first-v2.first)+(ll)(v1.second-v2.second)*(v1.second-v2.second));
}
inline int rev_bit(int bit,int len){
	int rev=0;
	for(int i=0;(1<<i)<len;i++){
		rev<<=1;
		if((1<<i)&bit) rev|=1;
	}
	return rev;
}
bool fin[1200040];
void exec_fft(cplex* f,int len,int o){
	for(int i=0;i<len;i++) fin[i]=false;
	for(int i=0;i<len;i++){
		if(!fin[i]){
			int rev=rev_bit(i,len);
			fin[rev]=fin[i]=true;
			swap(f[rev],f[i]);
		}
	}
	for(int s=2;s<=len;s<<=1){
		cplex mul=cplex(cos(2*pi*o/s),sin(2*pi*o/s));
		for(int j=0;j<len;j+=s){
			cplex e=cplex(1,0);
			for(int k=0;k<(s>>1);k++){
				cplex t=f[j+k+(s>>1)]*e;
				cplex u=f[j+k];
				f[j+k]=u+t;
				f[j+k+(s>>1)]=u-t;
				e*=mul;
			}
		}
	}
	if(o==-1){
		for(int i=0;i<len;i++)
			f[i]/=(double)len;
	}
}
cplex f[1200040],g[1200040];
ll solve_pp(){

	if(cross(a[0],a[1],c[0],c[1])==0){
		double d1=abs(cross(a[0],c[0],c[1]))/dist(c[0],c[1]);
		double d2=abs(cross(b[0],c[0],c[1]))/dist(c[0],c[1]);
		if(abs(d1-d2)<1e-10){
			// cout << "JIZZ\n";
			for(int i=0;i<l;i++)
				f[a[i].first+100000]=cplex(f[a[i].first+100000].real()+1,0);
			for(int i=0;i<m;i++)
				g[b[i].first+100000]=cplex(g[b[i].first+100000].real()+1,0);
			int sz=1;
			while(sz<=(400000)) sz<<=1;
			exec_fft(f,sz,1);
			exec_fft(g,sz,1);
			for(int i=0;i<sz;i++)
				f[i]*=g[i];
			exec_fft(f,sz,-1);
			ll ret=0;

			// for ( int i = 0 ; i < sz ; ++ i ) {
			// 	if ( static_cast< int >( floor(f[i].real()+0.3) ) ) {
			// 		cout << i << " meow\n";
			// 	}
			// }

			for(int i=0;i<n;i++){
				ret+=floor(f[c[i].first*2+200000].real()+0.3);
			}
			return ret;
		}else{
			return 0;
		}
	}else{
		// cout << "Obov\n";
		wtf x=get_point(a[0],a[1],c[0],c[1]);
		wtf y=get_point(b[0],b[1],c[0],c[1]);

		// cout << "("<<x.first.first<<"/"<<x.first.second<<","<<x.second.first<<"/"<<x.second.second<<")\n";
		// cout << "("<<y.first.first<<"/"<<y.first.second<<","<<y.second.first<<"/"<<y.second.second<<")\n";

		wtf z = wtf(
		{
			x.first.first*y.first.second+y.first.first*x.first.second,
			x.first.second*y.first.second
		},
		{
			x.second.first*y.second.second+x.second.second*y.second.first,
			x.second.second*y.second.second
		} );

		// pdd z=pdd((x.first+y.first),(x.second+y.second));
		for(int i=0;i<l;i++)
			adic[a[i]]++;
		for(int i=0;i<m;i++)
			bdic[b[i]]++;
		for(int i=0;i<n;i++)
			cdic[c[i]]++;
		ll ret=0;
		for(auto it=adic.begin();it!=adic.end();it++) {

			if ( ( z.first.first - it->first.first * z.first.second ) % z.first.second )
				continue;
			if ( ( z.second.first - it->first.second * z.second.second ) % z.second.second )
				continue;

			ret+=(ll)it->second*bdic[{ ( z.first.first - it->first.first * z.first.second ) / z.first.second, ( z.second.first - it->first.second * z.second.second ) / z.second.second }];
		}
		return ret;
	}
}

void solve_pin() {
	// cout << "MEOW\n";
	cout << solve_pp() << '\n';
}

void solve() {

	sort( a, a + l );
	sort( b, b + m );
	sort( c, c + m );

	if ( a[ l - 1 ] == a[ 0 ] and b[ m - 1 ] == b[ 0 ] ) {
		map< pair< int, int >, int > cnt;
		for ( int i = 0 ; i < n ; ++ i )
			cnt[ c[ i ] ]++;
		int dx = ( a[ 0 ].first + b[ 0 ].first );
		int dy = ( a[ 0 ].second + b[ 0 ].second );
		if ( ( dx & 1 ) or ( dy & 1 ) ) {
			cout << 0 << '\n';
		} else {
			dx >>= 1, dy >>= 1;
			cout << static_cast< lld >( cnt[ { dx, dy } ] ) * l * m << '\n';
		}
		return;
	} else if ( b[ m - 1 ] == b[ 0 ] and c[ n - 1 ] == c[ 0 ] ) {
		map< pair< int, int >, int > cnt;
		for ( int i = 0 ; i < l ; ++ i )
			cnt[ a[ i ] ]++;
		int dx = 2 * c[ 0 ].first - b[ 0 ].first;
		int dy = 2 * c[ 0 ].second - b[ 0 ].second;
		cout << static_cast< int >( cnt[ { dx, dy } ] ) * m * n << '\n';
		return;
	} else if ( c[ n - 1 ] == c[ 0 ] and a[ l - 1 ] == a[ 0 ] ) {
		map< pair< int, int >, int > cnt;
		for ( int i = 0 ; i < m ; ++ i )
			cnt[ b[ i ] ]++;
		int dx = 2 * c[ 0 ].first - a[ 0 ].first;
		int dy = 2 * c[ 0 ].second - a[ 0 ].second;
		cout << static_cast< int >( cnt[ { dx, dy } ] ) * n * l << '\n';
		return;
	}

	if ( a[ l - 1 ] == a[ 0 ] ) {
		a[ l ++ ] = { INF, INF };
	} else if ( b[ m - 1 ] == b[ 0 ] ) {
		b[ m ++ ] = { INF, INF };
	} else if ( c[ n - 1 ] == c[ 0 ] ) {
		c[ n ++ ] = { INF, INF };
	}

	swap( a[ 1 ], a[ l - 1 ] );
	swap( b[ 1 ], b[ m - 1 ] );
	swap( c[ 1 ], c[ n - 1 ] );


	const lld ax = ( a[ 0 ].first - a[ 1 ].first );
	const lld ay = ( a[ 0 ].second - a[ 1 ].second );

	const lld bx = ( b[ 0 ].first - b[ 1 ].first );
	const lld by = ( b[ 0 ].second - b[ 1 ].second );

	if ( ax * by - bx * ay == 0 ) {
		solve_pin();
	} else {
		solve_brute();
	}
}

int main() {
	ios_base::sync_with_stdio( false );
	cin.tie( nullptr );
	init(); solve();
	return 0;
}
accuracy: 0.3728813559322034
time_ms: 140
memory_kb: 20508
final_rank: 14

code_snippet: #include <bits/stdc++.h>
using namespace std;
using lld = int64_t;
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<double,double> pdd;
typedef complex<double> cplex;
const double pi=acos(-1);
const int INF = 500000;
const int N = 100000 + 5;

int l, m, n;

pair< int, int > a[ N ], b[ N ], c[ N ];

void init() {
	cin >> l >> m >> n;
	for ( int i = 0 ; i < l ; ++ i )
		cin >> a[ i ].first >> a[ i ].second;
	for ( int i = 0 ; i < m ; ++ i )
		cin >> b[ i ].first >> b[ i ].second;
	for ( int i = 0 ; i < n ; ++ i )
		cin >> c[ i ].first >> c[ i ].second;
}

void solve_brute() {
	map< pair< int, int >, lld > cntA, cntB;
	for ( int i = 0 ; i < l ; ++ i )
		cntA[ a[ i ] ] ++;
	for ( int i = 0 ; i < m ; ++ i )
		cntB[ b[ i ] ] ++;

	lld ans = 0;

	lld a0x = a[ 0 ].first, a0y = a[ 0 ].second;
	lld b0x = b[ 0 ].first, b0y = b[ 0 ].second;
	lld dax = a[ 1 ].first - a[ 0 ].first;
	lld day = a[ 1 ].second - a[ 0 ].second;
	lld dbx = b[ 1 ].first - b[ 0 ].first;
	lld dby = b[ 1 ].second - b[ 0 ].second;

	for ( int i = 0 ; i < n ; ++ i ) {
		lld cx = 2 * c[ i ].first, cy = 2 * c[ i ].second;
		cx -= a0x + b0x;
		cy -= a0y + b0y;

		lld det = dax * dby - dbx * day;
		lld ma = cx * dby - cy * dbx;
		lld mb = cy * dax - cx * day; 

		// cout << "MA = " << ma << '\n';
		// cout << "MB = " << mb << '\n';
		// cout << "DAX = " << dax <<'\n';
		// cout << "DAY = " << day << '\n';
		// cout << "DBX = " << dbx << '\n';
		// cout << "DBY = " << dby << '\n';
		// cout << "DET = " << det << '\n';

		if ( ( ma * dax ) % det != 0 ) continue;
		if ( ( ma * day ) % det != 0 ) continue;
		if ( ( mb * dbx ) % det != 0 ) continue;
		if ( ( mb * dby ) % det != 0 ) continue;

		// cout << "JIZZ\n";

		lld ax = a0x + ma * dax / det, ay = a0y + ma * day / det;
		lld bx = b0x + mb * dbx / det, by = b0y + mb * dby / det;

		ans += cntA[ { ax, ay } ] * cntB[ { bx, by } ];
	}
	cout << ans << '\n';
}

map<pdd,int> adic,bdic,cdic;
inline ll cross(pii o,pii a,pii b){
	return (a.first-o.first)*(b.second-o.second)-(a.second-o.second)*(b.first-o.first);
}
inline ll cross(pii v1,pii v2,pii v3,pii v4){
	return (v2.first-v1.first)*(v4.second-v3.second)-(v2.second-v1.second)*(v4.first-v3.first);
}
inline pdd get_point(pii v1,pii v2,pii v3,pii v4){
	ll a1=cross(v3,v1,v4),a2=cross(v3,v4,v2);
	double x=(double)(v1.first*a2+v2.first*a1)/(a1+a2);
	double y=(double)(v1.second*a2+v2.second*a1)/(a1+a2);
	return pdd(x,y);
}
inline double dist(pii v1,pii v2){
	return sqrt((ll)(v1.first-v2.first)*(v1.first-v2.first)+(ll)(v1.second-v2.second)*(v1.second-v2.second));
}
inline int rev_bit(int bit,int len){
	int rev=0;
	for(int i=0;(1<<i)<len;i++){
		rev<<=1;
		if((1<<i)&bit) rev|=1;
	}
	return rev;
}
bool fin[1200040];
void exec_fft(cplex* f,int len,int o){
	for(int i=0;i<len;i++) fin[i]=false;
	for(int i=0;i<len;i++){
		if(!fin[i]){
			int rev=rev_bit(i,len);
			fin[rev]=fin[i]=true;
			swap(f[rev],f[i]);
		}
	}
	for(int s=2;s<=len;s<<=1){
		cplex mul=cplex(cos(2*pi*o/s),sin(2*pi*o/s));
		for(int j=0;j<len;j+=s){
			cplex e=cplex(1,0);
			for(int k=0;k<(s>>1);k++){
				cplex t=f[j+k+(s>>1)]*e;
				cplex u=f[j+k];
				f[j+k]=u+t;
				f[j+k+(s>>1)]=u-t;
				e*=mul;
			}
		}
	}
	if(o==-1){
		for(int i=0;i<len;i++)
			f[i]/=(double)len;
	}
}
cplex f[1200040],g[1200040];
ll solve_pp(){
	if(cross(a[0],a[1],c[0],c[1])==0){
		double d1=abs(cross(a[0],c[0],c[1]))/dist(c[0],c[1]);
		double d2=abs(cross(b[0],c[0],c[1]))/dist(c[0],c[1]);
		if(abs(d1-d2)<1e-10){
			// cout << "JIZZ\n";
			for(int i=0;i<l;i++)
				f[a[i].first+100000]=cplex(f[a[i].first+100000].real()+1,0);
			for(int i=0;i<m;i++)
				g[b[i].first+100000]=cplex(g[b[i].first+100000].real()+1,0);
			int sz=1;
			while(sz<=(400000)) sz<<=1;
			exec_fft(f,sz,1);
			exec_fft(g,sz,1);
			for(int i=0;i<sz;i++)
				f[i]*=g[i];
			exec_fft(f,sz,-1);
			ll ret=0;

			// for ( int i = 0 ; i < sz ; ++ i ) {
			// 	if ( static_cast< int >( floor(f[i].real()+0.3) ) ) {
			// 		cout << i << " meow\n";
			// 	}
			// }

			for(int i=0;i<n;i++){
				ret+=floor(f[c[i].first*2+200000].real()+0.3);
			}
			return ret;
		}else{
			return 0;
		}
	}else{
		pdd x=get_point(a[0],a[1],c[0],c[1]);
		pdd y=get_point(b[0],b[1],c[0],c[1]);
		pdd z=pdd((x.first+y.first)/2,(x.second+y.second)/2);
		for(int i=0;i<l;i++)
			adic[a[i]]++;
		for(int i=0;i<m;i++)
			bdic[b[i]]++;
		for(int i=0;i<n;i++)
			cdic[c[i]]++;
		ll ret=0;
		for(auto it=adic.begin();it!=adic.end();it++)
			ret+=(ll)it->second*bdic[pdd(z.first*2-it->first.first,z.second*2-it->first.second)];
		return ret;
	}
}

void solve_pin() {
	cout << solve_pp() << '\n';
}

void solve() {
	if ( l == 1 and m == 1 ) {
		map< pair< int, int >, int > cnt;
		for ( int i = 0 ; i < n ; ++ i )
			cnt[ c[ i ] ]++;
		int dx = ( a[ 0 ].first + b[ 0 ].first );
		int dy = ( a[ 0 ].second + b[ 0 ].second );
		if ( ( dx & 1 ) or ( dy & 1 ) ) {
			cout << 0 << '\n';
		} else {
			dx >>= 1, dy >>= 1;
			cout << cnt[ { dx, dy } ] << '\n';
		}
		return;
	} else if ( m == 1 and n == 1 ) {
		map< pair< int, int >, int > cnt;
		for ( int i = 0 ; i < l ; ++ i )
			cnt[ a[ i ] ]++;
		int dx = 2 * c[ 0 ].first - b[ 0 ].first;
		int dy = 2 * c[ 0 ].second - b[ 0 ].second;
		cout << cnt[ { dx, dy } ] << '\n';
		return;
	} else if ( n == 1 and l == 1 ) {
		map< pair< int, int >, int > cnt;
		for ( int i = 0 ; i < m ; ++ i )
			cnt[ b[ i ] ]++;
		int dx = 2 * c[ 0 ].first - a[ 0 ].first;
		int dy = 2 * c[ 0 ].second - a[ 0 ].second;
		cout << cnt[ { dx, dy } ] << '\n';
		return;
	}
	if ( l == 1 ) {
		a[ l ++ ] = { INF, INF };
	} else if ( m == 1 ) {
		b[ m ++ ] = { INF, INF };
	} else if ( n == 1 ) {
		c[ n ++ ] = { INF, INF };
	}

	const lld ax = ( a[ 0 ].first - a[ 1 ].first );
	const lld ay = ( a[ 0 ].second - a[ 1 ].second );
	const lld bx = ( b[ 0 ].first - b[ 1 ].first );
	const lld by = ( b[ 0 ].second - b[ 1 ].second );

	if ( ax * by - bx * ay == 0 ) {
		solve_pin();
	} else {
		solve_brute();
	}
}

int main() {
	ios_base::sync_with_stdio( false );
	cin.tie( nullptr );
	init(); solve();
	return 0;
}
accuracy: 0.2033898305084746
time_ms: 150
memory_kb: 20392
final_rank: 18

code_snippet: bool debug=false;
#include <algorithm>
#include <stdio.h>
#include <vector>
#include <utility>
#include <map>
#include <math.h>
using namespace std;
#define PB push_back
#define F first
#define S second
const int INF=1e9+10;
const int N=1e5+10;
const double pi=acos(-1);
pair<int,int> getmid(pair<int,int> a,pair<int,int> b){
	if(((a.F+b.F)&1)||((a.S+b.S)&1))return {INF,INF};
	return {(a.F+b.F)>>1,(a.S+b.S)>>1};
}
pair<int,int> getnxt(pair<int,int> a,pair<int,int> c){
	return {(c.F-a.F)*2+a.F,(c.S-a.S)*2+a.S};
}
__int128 myabs(__int128 x){return x>0?x:-x;}
pair<int,int> intersect(__int128 Aa,__int128 Ba,__int128 Ca,__int128 Ab,__int128 Bb,__int128 Cb){
	__int128 x=Ba*Cb-Bb*Ca,y=Ca*Ab-Cb*Aa,det=Ba*Ab-Aa*Bb;
	if(x%det!=0)return {INF,INF};
	if(y%det!=0)return {INF,INF};
	x/=det;
	y/=det;
	if(myabs(x)>N)return {INF,INF};
	if(myabs(y)>N)return {INF,INF};
	return {x,y};
}
pair<double,double> mul(pair<double,double> a,pair<double,double> b){
	return {a.F*b.F-a.S*b.S,a.F*b.S+a.S*b.F};
}
void fft(vector<pair<double,double>>& v,int size,bool on){
    pair<double,double> wn,u,t,w,inv;
	for(int i=1,j=size>>1,k;i<(size-1);i++){
        if(i<j)swap(v[i],v[j]);
        k=size>>1;
        while(j&k){
            j^=k;
            k>>=1;
        }
        j|=k;
    }
    for(int i=2;i<=size;i<<=1){
        wn={cos(2*pi/i),sin(2*pi/i)};
		if(on)wn.S=-wn.S;
        for(int j=0;j<size;j+=i){
            w={1,0};
            for(int k=j;k<j+(i>>1);k++){
                u=v[k];
                t=mul(w,v[k+(i>>1)]);
                v[k]={u.F+t.F,u.S+t.S};
                v[k+(i>>1)]={u.F-t.F,u.S-t.S};
                w=mul(wn,w);
            }
        }
    }
    if(on){
        inv={1.0/size,0};
        for(int i=0;i<size;i++)v[i]=mul(v[i],inv);
    }
    return ;
}
long long int allsame(vector<pair<int,int>>&va,vector<pair<int,int>>&vb,vector<pair<int,int>>&vc){
	vector<pair<double,double>> a,b;
	vector<long long int> c;
	long long int ans=0;
	int n=N<<2,sz=1;
	while(sz<n)sz<<=1;
	a.resize(sz,{0,0});
	b.resize(sz,{0,0});
	c.resize(sz>>1,0);
	if(va[0].F==va.back().F){
		for(pair<int,int> i:va)a[i.S+N].F+=1;
		for(pair<int,int> i:vb)b[i.S+N].F+=1;
		for(pair<int,int> i:vc)c[i.S+N]++;
	}
	else{
		for(pair<int,int> i:va)a[i.F+N].F+=1;
		for(pair<int,int> i:vb)b[i.F+N].F+=1;
		for(pair<int,int> i:vc)c[i.F+N]++;
	}
	if(debug){
		printf("a::\n");for(int i=0;i<sz;i++)if(a[i].F>0)printf("%d::(%.2lf,%.2lf)\n",i,a[i].F,a[i].S);
		printf("b::\n");for(int i=0;i<sz;i++)if(b[i].F>0)printf("%d::(%.2lf,%.2lf)\n",i,b[i].F,b[i].S);
	}
	fft(a,sz,0);
	fft(b,sz,0);
	for(int i=0;i<a.size();i++)a[i]=mul(a[i],b[i]);
	fft(a,sz,1);
	if(debug){
		printf("after::\n");for(int i=0;i<sz;i++)if(a[i].F>0)printf("%d::(%.2lf,%.2lf)\n",i,a[i].F,a[i].S);
		printf("c::\n");for(int i=0;i<(sz>>1);i++)if(c[i]>0)printf("%d::%d\n",i,c[i]);
	}
	for(int i=0;i<(sz>>1);i++)ans+=c[i]*((long long int)(a[i<<1].F+0.5));
	return ans;
}
long long int ABsame(vector<pair<int,int>>&va,vector<pair<int,int>>&vb,vector<pair<int,int>>&vc){
	vector<pair<double,double>> a,b;
	int n=N<<2,sz=1;
	pair<int,int> temp;
	long long int Aa,Ba,Ca,Cb,Ac,Bc,Cc;
	while(sz<n)sz<<=1;
	a.resize(sz,{0,0});
	b.resize(sz,{0,0});
	if(va[0].F==va.back().F){
		for(pair<int,int> i:va)a[i.S+N].F+=1;
		for(pair<int,int> i:vb)b[i.S+N].F+=1;
	}
	else{
		for(pair<int,int> i:va)a[i.F+N].F+=1;
		for(pair<int,int> i:vb)b[i.F+N].F+=1;
	}
	fft(a,sz,0);
	fft(b,sz,0);
	for(int i=0;i<a.size();i++)a[i]=mul(a[i],b[i]);
	fft(a,sz,1);
	Aa=va[0].S-va.back().S,Ba=va.back().F-va[0].F;
	Ca=Aa*va[0].F+Ba*va[0].S;
	Cb=Aa*vb[0].F+Ba*vb[0].S;
	Ac=vc[0].S-vc.back().S,Bc=vc.back().F-vc[0].F;
	Cc=Ac*vc[0].F+Bc*vc[0].S;
	temp=intersect(Aa*2,Ba*2,Ca+Cb,Ac,Bc,Cc);
	if(va[0].F==va.back().F)return ((long long int)(a[(temp.S+N)<<1].F+0.5))*(upper_bound(vc.begin(),vc.end(),temp)-lower_bound(vc.begin(),vc.end(),temp));
	else return ((long long int)(a[(temp.S+N)<<1].F+0.5))*(upper_bound(vc.begin(),vc.end(),temp)-lower_bound(vc.begin(),vc.end(),temp));
}
long long int ACsame(vector<pair<int,int>>&va,vector<pair<int,int>>&vb,vector<pair<int,int>>&vc){
	vector<pair<double,double>>a,b;
	vector<long long int> c;
	int n=N<<2,sz=1;
	long long int ans=0,Aa,Ba,Ca,Ab,Bb,Cb,Cc;
	pair<int,int> temp;
	while(sz<n)sz<<=1;
	a.resize(sz,{0,0});
	b.resize(sz,{0,0});
	c.resize(sz>>1,0);
	Aa=va[0].S-va.back().S,Ba=va.back().F-va[0].F;
	Ca=Aa*va[0].F+Ba*va[0].S;
	Cc=Aa*vc[0].F+Ba*vc[0].S;
	Ab=vb[0].S-vb.back().S,Bb=vb.back().F-vb[0].F;
	Cb=Ab*vb[0].F+Bb*vb[0].S;
	temp=intersect(Aa,Ba,Cc*2-Ca,Ab,Bb,Cb);
	if(temp.F>=N||temp.S>=N)return 0;
	if(va[0].F==va.back().F){
		for(pair<int,int> i:va)a[i.S+N].F+=1;
		for(pair<int,int> i:vc)c[i.S+N]++;
		b[temp.S+N].F=upper_bound(vb.begin(),vb.end(),temp)-lower_bound(vb.begin(),vb.end(),temp);
	}
	else{
		for(pair<int,int> i:va)a[i.F+N].F+=1;
		for(pair<int,int> i:vc)c[i.F+N]++;
		b[temp.F+N].F=upper_bound(vb.begin(),vb.end(),temp)-lower_bound(vb.begin(),vb.end(),temp);
	}
	fft(a,sz,0);
	fft(b,sz,0);
	for(int i=0;i<sz;i++)a[i]=mul(a[i],b[i]);
	fft(a,sz,1);
	for(int i=0;i<(sz>>1);i++)ans+=c[i]*((long long int)(a[i<<1].F+0.5));
	return ans;
}
int main(){
	int a,b,c;
	__int128 Aa,Ab,Ac,Ba,Bb,Bc,Ca,Cb,Cc;
	long long int ans=0;
	map<pair<int,int>,long long int> ma,mb,mc;
	map<pair<int,int>,long long int>::iterator u,t;
	pair<int,int> temp;
	vector<pair<int,int>> va,vb,vc;
	scanf("%d%d%d",&a,&b,&c);
	for(int i=1;i<=a;i++){
		scanf("%d%d",&temp.F,&temp.S);
		va.PB(temp);
		ma[temp]++;
	}
	for(int i=1;i<=b;i++){
		scanf("%d%d",&temp.F,&temp.S);
		vb.PB(temp);
		mb[temp]++;
	}
	for(int i=1;i<=c;i++){
		scanf("%d%d",&temp.F,&temp.S);
		vc.PB(temp);
		mc[temp]++;
	}
	if(ma.size()==1)for(int i=0;i<b;i++)ans+=mc[getmid(va[0],vb[i])]*a;
	else if(mb.size()==1)for(int i=0;i<a;i++)ans+=mc[getmid(va[i],vb[0])]*b;
	else if(mc.size()==1)for(int i=0;i<a;i++)ans+=mb[getnxt(va[i],vc[0])]*c;
	else{
		u=ma.begin(),t=ma.end();
		t--;
		Aa=u->F.S-t->F.S,Ba=t->F.F-u->F.F;
		Ca=Aa*(u->F.F)+Ba*(u->F.S);
		u=mb.begin(),t=mb.end();
		t--;
		Ab=u->F.S-t->F.S,Bb=t->F.F-u->F.F;
		Cb=Ab*(u->F.F)+Bb*(u->F.S);
		u=mc.begin(),t=mc.end();
		t--;
		Ac=u->F.S-t->F.S,Bc=t->F.F-u->F.F;
		Cc=Ac*(u->F.F)+Bc*(u->F.S);
		if(Aa==0){
			if(Ab==0){
				if(Ac==0){
					if(Cc*Bb*Ba*2==Ca*Bb*Bc+Cb*Ba*Bc)ans=allsame(va,vb,vc);
					else ans=0;
				}
				else ans=ABsame(va,vb,vc);
			}
			else if(Ac==0)ans=ACsame(va,vb,vc);
			else if(Ab*Bc==Bb*Ac)ans=ACsame(vb,va,vc);
			else {
				for(pair<pair<int,int>,long long int> i:mb){
					temp=intersect(Aa,Ba,Ca,Ac,Bc,Cc*2-Ac*i.F.F-Bc*i.F.S);
					ans+=ma[temp]*mc[getmid(temp,i.F)]*i.S;
				}
			}
		}
		else if(Ba==0){
			if(Bb==0){
				if(Bc==0){
					if(Cc*Aa*Ab*2==Ca*Ab*Ac+Cb*Aa*Ac)ans=allsame(va,vb,vc);
					else ans=0;
				}
				else ans=ABsame(va,vb,vc);
			}
			else if(Bc==0)ans=ACsame(va,vb,vc);
			else if(Ab*Bc==Bb*Ac)ans=ACsame(vb,va,vc);
			else{
				for(pair<pair<int,int>,long long int> i:mb){
					temp=intersect(Aa,Ba,Ca,Ac,Bc,Cc*2-Ac*i.F.F-Bc*i.F.S);
					ans+=ma[temp]*mc[getmid(temp,i.F)]*i.S;
				}
			}
		}
		else if(Ab==0){
			if(Ac==0)ans=ACsame(vb,va,vc);
			else if(Aa*Bc==Ac*Ba)ans=ACsame(va,vb,vc);
			else {
				for(pair<pair<int,int>,long long int> i:mb){
					temp=intersect(Aa,Ba,Ca,Ac,Bc,Cc*2-Ac*i.F.F-Bc*i.F.S);
					ans+=ma[temp]*mc[getmid(temp,i.F)]*i.S;
				}
			}
		}
		else if(Bb==0){
			if(Bc==0)ans=ACsame(vb,va,vc);
			else if(Aa*Bc==Ac*Ba)ans=ACsame(va,vb,vc);
			else{
				for(pair<pair<int,int>,long long int> i:mb){
					temp=intersect(Aa,Ba,Ca,Ac,Bc,Cc*2-Ac*i.F.F-Bc*i.F.S);
					ans+=ma[temp]*mc[getmid(temp,i.F)]*i.S;
				}
			}
		}
		else if(Aa*Bb==Ab*Ba){
			if(Ab*Bc==Bb*Ac){
				if(Cc*Ab*Aa*2==Ca*Ab*Ac+Cb*Aa*Ac)ans=allsame(va,vb,vc);
				else ans=0;
			}
			else ans=ABsame(va,vb,vc);
		}
		else if(Bb*Ac==Bc*Ab)ans=ACsame(vb,va,vc);
		else if(Aa*Bc==Ac*Ba)ans=ACsame(va,vb,vc);
		else{
			for(pair<pair<int,int>,long long int> i:mb){
				temp=intersect(Aa,Ba,Ca,Ac,Bc,Cc*2-Ac*i.F.F-Bc*i.F.S);
				ans+=ma[temp]*mc[getmid(temp,i.F)]*i.S;
			}
		}
	}
	printf("%lld\n",ans);
}
accuracy: 1
time_ms: 190
memory_kb: 41996
final_rank: 3

code_snippet: bool debug=false;
#include <algorithm>
#include <stdio.h>
#include <vector>
#include <utility>
#include <map>
#include <math.h>
using namespace std;
#define PB push_back
#define F first
#define S second
const int INF=1e9+10;
const int N=1e5+10;
const double pi=acos(-1);
pair<int,int> getmid(pair<int,int> a,pair<int,int> b){
	if(((a.F+b.F)&1)||((a.S+b.S)&1))return {INF,INF};
	return {(a.F+b.F)>>1,(a.S+b.S)>>1};
}
pair<int,int> getnxt(pair<int,int> a,pair<int,int> c){
	return {(c.F-a.F)*2+a.F,(c.S-a.S)*2+a.S};
}
__int128 myabs(__int128 x){return x>0?x:-x;}
pair<int,int> intersect(__int128 Aa,__int128 Ba,__int128 Ca,__int128 Ab,__int128 Bb,__int128 Cb){
	__int128 x=Ba*Cb-Bb*Ca,y=Ca*Ab-Cb*Aa,det=Ba*Ab-Aa*Bb;
	if(x%det!=0)return {INF,INF};
	if(y%det!=0)return {INF,INF};
	x/=det;
	y/=det;
	if(myabs(x)>N)return {INF,INF};
	if(myabs(y)>N)return {INF,INF};
	return {x,y};
}
pair<double,double> mul(pair<double,double> a,pair<double,double> b){
	return {a.F*b.F-a.S*b.S,a.F*b.S+a.S*b.F};
}
void fft(vector<pair<double,double>>& v,int size,bool on){
    pair<double,double> wn,u,t,w,inv;
	for(int i=1,j=size>>1,k;i<(size-1);i++){
        if(i<j)swap(v[i],v[j]);
        k=size>>1;
        while(j&k){
            j^=k;
            k>>=1;
        }
        j|=k;
    }
    for(int i=2;i<=size;i<<=1){
        wn={cos(2*pi/i),sin(2*pi/i)};
		if(on)wn.S=-wn.S;
        for(int j=0;j<size;j+=i){
            w={1,0};
            for(int k=j;k<j+(i>>1);k++){
                u=v[k];
                t=mul(w,v[k+(i>>1)]);
                v[k]={u.F+t.F,u.S+t.S};
                v[k+(i>>1)]={u.F-t.F,u.S-t.S};
                w=mul(wn,w);
            }
        }
    }
    if(on){
        inv={1.0/size,0};
        for(int i=0;i<size;i++)v[i]=mul(v[i],inv);
    }
    return ;
}
long long int allsame(vector<pair<int,int>>&va,vector<pair<int,int>>&vb,vector<pair<int,int>>&vc){
	vector<pair<double,double>> a,b;
	vector<long long int> c;
	long long int ans=0;
	int n=N<<2,sz=1;
	while(sz<n)sz<<=1;
	a.resize(sz,{0,0});
	b.resize(sz,{0,0});
	c.resize(sz>>1,0);
	if(va[0].F==va.back().F){
		for(pair<int,int> i:va)a[i.S+N].F+=1;
		for(pair<int,int> i:vb)b[i.S+N].F+=1;
		for(pair<int,int> i:vc)c[i.S+N]++;
	}
	else{
		for(pair<int,int> i:va)a[i.F+N].F+=1;
		for(pair<int,int> i:vb)b[i.F+N].F+=1;
		for(pair<int,int> i:vc)c[i.F+N]++;
	}
	if(debug){
		printf("a::\n");for(int i=0;i<sz;i++)if(a[i].F>0)printf("%d::(%.2lf,%.2lf)\n",i,a[i].F,a[i].S);
		printf("b::\n");for(int i=0;i<sz;i++)if(b[i].F>0)printf("%d::(%.2lf,%.2lf)\n",i,b[i].F,b[i].S);
	}
	fft(a,sz,0);
	fft(b,sz,0);
	for(int i=0;i<a.size();i++)a[i]=mul(a[i],b[i]);
	fft(a,sz,1);
	if(debug){
		printf("after::\n");for(int i=0;i<sz;i++)if(a[i].F>0)printf("%d::(%.2lf,%.2lf)\n",i,a[i].F,a[i].S);
		printf("c::\n");for(int i=0;i<(sz>>1);i++)if(c[i]>0)printf("%d::%d\n",i,c[i]);
	}
	for(int i=0;i<(sz>>1);i++)ans+=c[i]*((long long int)(a[i<<1].F+0.5));
	return ans;
}
long long int ABsame(vector<pair<int,int>>&va,vector<pair<int,int>>&vb,vector<pair<int,int>>&vc){
	vector<pair<double,double>> a,b;
	int n=N<<2,sz=1;
	pair<int,int> temp;
	long long int Aa,Ba,Ca,Cb,Ac,Bc,Cc;
	while(sz<n)sz<<=1;
	a.resize(sz,{0,0});
	b.resize(sz,{0,0});
	if(va[0].F==va.back().F){
		for(pair<int,int> i:va)a[i.S+N].F+=1;
		for(pair<int,int> i:vb)b[i.S+N].F+=1;
	}
	else{
		for(pair<int,int> i:va)a[i.F+N].F+=1;
		for(pair<int,int> i:vb)b[i.F+N].F+=1;
	}
	fft(a,sz,0);
	fft(b,sz,0);
	for(int i=0;i<a.size();i++)a[i]=mul(a[i],b[i]);
	fft(a,sz,1);
	Aa=va[0].S-va.back().S,Ba=va.back().F-va[0].F;
	Ca=Aa*va[0].F+Ba*va[0].S;
	Cb=Aa*vb[0].F+Ba*vb[0].S;
	Ac=vc[0].S-vc.back().S,Bc=vc.back().F-vc[0].F;
	Cc=Ac*vc[0].F+Bc*vc[0].S;
	temp=intersect(Aa*2,Ba*2,Ca+Cb,Ac,Bc,Cc);
	if(va[0].F==va.back().F)return ((long long int)(a[(temp.S+N)<<1].F+0.5))*(upper_bound(vc.begin(),vc.end(),temp)-lower_bound(vc.begin(),vc.end(),temp));
	else return ((long long int)(a[(temp.S+N)<<1].F+0.5))*(upper_bound(vc.begin(),vc.end(),temp)-lower_bound(vc.begin(),vc.end(),temp));
}
long long int ACsame(vector<pair<int,int>>&va,vector<pair<int,int>>&vb,vector<pair<int,int>>&vc){
	vector<pair<double,double>>a,b;
	vector<long long int> c;
	int n=N<<2,sz=1;
	long long int ans=0,Aa,Ba,Ca,Ab,Bb,Cb,Cc;
	pair<int,int> temp;
	while(sz<n)sz<<=1;
	a.resize(sz,{0,0});
	b.resize(sz,{0,0});
	c.resize(sz>>1,0);
	Aa=va[0].S-va.back().S,Ba=va.back().F-va[0].F;
	Ca=Aa*va[0].F+Ba*va[0].S;
	Cc=Aa*vc[0].F+Ba*vc[0].S;
	Ab=vb[0].S-vb.back().S,Bb=vb.back().F-vb[0].F;
	Cb=Ab*vb[0].F+Bb*vb[0].S;
	temp=intersect(Aa,Ba,Cc*2-Ca,Ab,Bb,Cb);
	if(va[0].F==va.back().F){
		for(pair<int,int> i:va)a[i.S+N].F+=1;
		for(pair<int,int> i:vc)c[i.S+N]++;
		b[temp.S+N].F=upper_bound(vb.begin(),vb.end(),temp)-lower_bound(vb.begin(),vb.end(),temp);
	}
	else{
		for(pair<int,int> i:va)a[i.F+N].F+=1;
		for(pair<int,int> i:vc)c[i.F+N]++;
		b[temp.F+N].F=upper_bound(vb.begin(),vb.end(),temp)-lower_bound(vb.begin(),vb.end(),temp);
	}
	fft(a,sz,0);
	fft(b,sz,0);
	for(int i=0;i<sz;i++)a[i]=mul(a[i],b[i]);
	fft(a,sz,1);
	for(int i=0;i<(sz>>1);i++)ans+=c[i]*((long long int)(a[i<<1].F+0.5));
	return ans;
}
int main(){
	int a,b,c;
	__int128 Aa,Ab,Ac,Ba,Bb,Bc,Ca,Cb,Cc;
	long long int ans=0;
	map<pair<int,int>,long long int> ma,mb,mc;
	map<pair<int,int>,long long int>::iterator u,t;
	pair<int,int> temp;
	vector<pair<int,int>> va,vb,vc;
	scanf("%d%d%d",&a,&b,&c);
	for(int i=1;i<=a;i++){
		scanf("%d%d",&temp.F,&temp.S);
		va.PB(temp);
		ma[temp]++;
	}
	for(int i=1;i<=b;i++){
		scanf("%d%d",&temp.F,&temp.S);
		vb.PB(temp);
		mb[temp]++;
	}
	for(int i=1;i<=c;i++){
		scanf("%d%d",&temp.F,&temp.S);
		vc.PB(temp);
		mc[temp]++;
	}
	if(ma.size()==1)for(int i=0;i<b;i++)ans+=mc[getmid(va[0],vb[i])]*a;
	else if(mb.size()==1)for(int i=0;i<a;i++)ans+=mc[getmid(va[i],vb[0])]*b;
	else if(mc.size()==1)for(int i=0;i<a;i++)ans+=mb[getnxt(va[i],vc[0])]*c;
	else{
		u=ma.begin(),t=ma.end();
		t--;
		Aa=u->F.S-t->F.S,Ba=t->F.F-u->F.F;
		Ca=Aa*(u->F.F)+Ba*(u->F.S);
		u=mb.begin(),t=mb.end();
		t--;
		Ab=u->F.S-t->F.S,Bb=t->F.F-u->F.F;
		Cb=Ab*(u->F.F)+Bb*(u->F.S);
		u=mc.begin(),t=mc.end();
		t--;
		Ac=u->F.S-t->F.S,Bc=t->F.F-u->F.F;
		Cc=Ac*(u->F.F)+Bc*(u->F.S);
		if(Aa==0){
			if(Ab==0){
				if(Ac==0){
					if(Cc*Bb*Ba*2==Ca*Bb*Bc+Cb*Ba*Bc)ans=allsame(va,vb,vc);
					else ans=0;
				}
				else ans=ABsame(va,vb,vc);
			}
			else if(Ac==0)ans=ACsame(va,vb,vc);
			else if(Ab*Bc==Bb*Ac)ans=ACsame(vb,va,vc);
			else {
				for(pair<pair<int,int>,long long int> i:mb){
					temp=intersect(Aa,Ba,Ca,Ac,Bc,Cc*2-Ac*i.F.F-Bc*i.F.S);
					ans+=ma[temp]*mc[getmid(temp,i.F)]*i.S;
				}
			}
		}
		else if(Ba==0){
			if(Bb==0){
				if(Bc==0){
					if(Cc*Aa*Ab*2==Ca*Ab*Ac+Cb*Aa*Ac)ans=allsame(va,vb,vc);
					else ans=0;
				}
				else ans=ABsame(va,vb,vc);
			}
			else if(Bc==0)ans=ACsame(va,vb,vc);
			else if(Ab*Bc==Bb*Ac)ans=ACsame(vb,va,vc);
			else{
				for(pair<pair<int,int>,long long int> i:mb){
					temp=intersect(Aa,Ba,Ca,Ac,Bc,Cc*2-Ac*i.F.F-Bc*i.F.S);
					ans+=ma[temp]*mc[getmid(temp,i.F)]*i.S;
				}
			}
		}
		else if(Ab==0){
			if(Ac==0)ans=ACsame(vb,va,vc);
			else if(Aa*Bc==Ac*Ba)ans=ACsame(va,vb,vc);
			else {
				for(pair<pair<int,int>,long long int> i:mb){
					temp=intersect(Aa,Ba,Ca,Ac,Bc,Cc*2-Ac*i.F.F-Bc*i.F.S);
					ans+=ma[temp]*mc[getmid(temp,i.F)]*i.S;
				}
			}
		}
		else if(Bb==0){
			if(Bc==0)ans=ACsame(vb,va,vc);
			else if(Aa*Bc==Ac*Ba)ans=ACsame(va,vb,vc);
			else{
				for(pair<pair<int,int>,long long int> i:mb){
					temp=intersect(Aa,Ba,Ca,Ac,Bc,Cc*2-Ac*i.F.F-Bc*i.F.S);
					ans+=ma[temp]*mc[getmid(temp,i.F)]*i.S;
				}
			}
		}
		else if(Aa*Bb==Ab*Ba){
			if(Ab*Bc==Bb*Ac){
				if(Cc*Ab*Aa*2==Ca*Ab*Ac+Cb*Aa*Ac)ans=allsame(va,vb,vc);
				else ans=0;
			}
			else ans=ABsame(va,vb,vc);
		}
		else if(Bb*Ac==Bc*Ab)ans=ACsame(vb,va,vc);
		else if(Aa*Bc==Ac*Ba)ans=ACsame(va,vb,vc);
		else{
			for(pair<pair<int,int>,long long int> i:mb){
				temp=intersect(Aa,Ba,Ca,Ac,Bc,Cc*2-Ac*i.F.F-Bc*i.F.S);
				ans+=ma[temp]*mc[getmid(temp,i.F)]*i.S;
			}
		}
	}
	printf("%lld\n",ans);
}
accuracy: 0.5932203389830508
time_ms: 190
memory_kb: 37908
final_rank: 12

code_snippet: bool debug=false;
#include <algorithm>
#include <stdio.h>
#include <vector>
#include <utility>
#include <map>
#include <math.h>
using namespace std;
#define PB push_back
#define F first
#define S second
const int INF=1e9+10;
const int N=1e5+10;
const double pi=acos(-1);
pair<int,int> getmid(pair<int,int> a,pair<int,int> b){
	if(((a.F+b.F)&1)||((a.S+b.S)&1))return {INF,INF};
	return {(a.F+b.F)>>1,(a.S+b.S)>>1};
}
pair<int,int> getnxt(pair<int,int> a,pair<int,int> c){
	return {(c.F-a.F)*2+a.F,(c.S-a.S)*2+a.S};
}
__int128 myabs(__int128 x){return x>0?x:-x;}
pair<int,int> intersect(__int128 Aa,__int128 Ba,__int128 Ca,__int128 Ab,__int128 Bb,__int128 Cb){
	__int128 x=Ba*Cb-Bb*Ca,y=Ca*Ab-Cb*Aa,det=Ba*Ab-Aa*Bb;
	if(x%det!=0)return {INF,INF};
	if(y%det!=0)return {INF,INF};
	x/=det;
	y/=det;
	if(myabs(x)>N)return {INF,INF};
	if(myabs(y)>N)return {INF,INF};
	return {(int)x,(int)y};
}
pair<double,double> mul(pair<double,double> a,pair<double,double> b){
	return {a.F*b.F-a.S*b.S,a.F*b.S+a.S*b.F};
}
void fft(vector<pair<double,double>>& v,int size,bool on){
    pair<double,double> wn,u,t,w,inv;
	for(int i=1,j=size>>1,k;i<(size-1);i++){
        if(i<j)swap(v[i],v[j]);
        k=size>>1;
        while(j&k){
            j^=k;
            k>>=1;
        }
        j|=k;
    }
    for(int i=2;i<=size;i<<=1){
        wn={cos(2*pi/i),sin(2*pi/i)};
		if(on)wn.S=-wn.S;
        for(int j=0;j<size;j+=i){
            w={1,0};
            for(int k=j;k<j+(i>>1);k++){
                u=v[k];
                t=mul(w,v[k+(i>>1)]);
                v[k]={u.F+t.F,u.S+t.S};
                v[k+(i>>1)]={u.F-t.F,u.S-t.S};
                w=mul(wn,w);
            }
        }
    }
    if(on){
        inv={1.0/size,0};
        for(int i=0;i<size;i++)v[i]=mul(v[i],inv);
    }
    return ;
}
long long int allsame(vector<pair<int,int>>&va,vector<pair<int,int>>&vb,vector<pair<int,int>>&vc){
	vector<pair<double,double>> a,b;
	vector<long long int> c;
	long long int ans=0;
	int n=N<<2,sz=1;
	while(sz<n)sz<<=1;
	a.resize(sz,{0,0});
	b.resize(sz,{0,0});
	c.resize(sz>>1,0);
	if(va[0].F==va.back().F){
		for(pair<int,int> i:va)a[i.S+N].F+=1;
		for(pair<int,int> i:vb)b[i.S+N].F+=1;
		for(pair<int,int> i:vc)c[i.S+N]++;
	}
	else{
		for(pair<int,int> i:va)a[i.F+N].F+=1;
		for(pair<int,int> i:vb)b[i.F+N].F+=1;
		for(pair<int,int> i:vc)c[i.F+N]++;
	}
	if(debug){
		printf("a::\n");for(int i=0;i<sz;i++)if(a[i].F>0)printf("%d::(%.2lf,%.2lf)\n",i,a[i].F,a[i].S);
		printf("b::\n");for(int i=0;i<sz;i++)if(b[i].F>0)printf("%d::(%.2lf,%.2lf)\n",i,b[i].F,b[i].S);
	}
	fft(a,sz,0);
	fft(b,sz,0);
	for(int i=0;i<a.size();i++)a[i]=mul(a[i],b[i]);
	fft(a,sz,1);
	if(debug){
		printf("after::\n");for(int i=0;i<sz;i++)if(a[i].F>0)printf("%d::(%.2lf,%.2lf)\n",i,a[i].F,a[i].S);
		printf("c::\n");for(int i=0;i<(sz>>1);i++)if(c[i]>0)printf("%d::%d\n",i,c[i]);
	}
	for(int i=0;i<(sz>>1);i++)ans+=c[i]*((long long int)(a[i<<1].F+0.5));
	return ans;
}
long long int ABsame(vector<pair<int,int>>&va,vector<pair<int,int>>&vb,vector<pair<int,int>>&vc){
	vector<pair<double,double>> a,b;
	int n=N<<2,sz=1;
	pair<int,int> temp;
	long long int Aa,Ba,Ca,Cb,Ac,Bc,Cc;
	while(sz<n)sz<<=1;
	a.resize(sz,{0,0});
	b.resize(sz,{0,0});
	if(va[0].F==va.back().F){
		for(pair<int,int> i:va)a[i.S+N].F+=1;
		for(pair<int,int> i:vb)b[i.S+N].F+=1;
	}
	else{
		for(pair<int,int> i:va)a[i.F+N].F+=1;
		for(pair<int,int> i:vb)b[i.F+N].F+=1;
	}
	fft(a,sz,0);
	fft(b,sz,0);
	for(int i=0;i<a.size();i++)a[i]=mul(a[i],b[i]);
	fft(a,sz,1);
	Aa=va[0].S-va.back().S,Ba=va.back().F-va[0].F;
	Ca=Aa*va[0].F+Ba*va[0].S;
	Cb=Aa*vb[0].F+Ba*vb[0].S;
	Ac=vc[0].S-vc.back().S,Bc=vc.back().F-vc[0].F;
	Cc=Ac*vc[0].F+Bc*vc[0].S;
	temp=intersect(Aa*2,Ba*2,Ca+Cb,Ac,Bc,Cc);
	if(va[0].F==va.back().F)return ((long long int)(a[(temp.S+N)<<1].F+0.5))*(upper_bound(vc.begin(),vc.end(),temp)-lower_bound(vc.begin(),vc.end(),temp));
	else return ((long long int)(a[(temp.S+N)<<1].F+0.5))*(upper_bound(vc.begin(),vc.end(),temp)-lower_bound(vc.begin(),vc.end(),temp));
}
long long int ACsame(vector<pair<int,int>>&va,vector<pair<int,int>>&vb,vector<pair<int,int>>&vc){
	vector<pair<double,double>>a,b;
	vector<long long int> c;
	int n=N<<2,sz=1;
	long long int ans=0,Aa,Ba,Ca,Ab,Bb,Cb,Cc;
	pair<int,int> temp;
	while(sz<n)sz<<=1;
	a.resize(sz,{0,0});
	b.resize(sz,{0,0});
	c.resize(sz>>1,0);
	Aa=va[0].S-va.back().S,Ba=va.back().F-va[0].F;
	Ca=Aa*va[0].F+Ba*va[0].S;
	Cc=Aa*vc[0].F+Ba*vc[0].S;
	Ab=vb[0].S-vb.back().S,Bb=vb.back().F-vb[0].F;
	Cb=Ab*vb[0].F+Bb*vb[0].S;
	temp=intersect(Aa,Ba,Cc*2-Ca,Ab,Bb,Cb);
	if(va[0].F==va.back().F){
		for(pair<int,int> i:va)a[i.S+N].F+=1;
		for(pair<int,int> i:vc)c[i.S+N]++;
		b[temp.S+N].F=upper_bound(vb.begin(),vb.end(),temp)-lower_bound(vb.begin(),vb.end(),temp);
	}
	else{
		for(pair<int,int> i:va)a[i.F+N].F+=1;
		for(pair<int,int> i:vc)c[i.F+N]++;
		b[temp.F+N].F=upper_bound(vb.begin(),vb.end(),temp)-lower_bound(vb.begin(),vb.end(),temp);
	}
	fft(a,sz,0);
	fft(b,sz,0);
	for(int i=0;i<sz;i++)a[i]=mul(a[i],b[i]);
	fft(a,sz,1);
	for(int i=0;i<(sz>>1);i++)ans+=c[i]*((long long int)(a[i<<1].F+0.5));
	return ans;
}
int main(){
	int a,b,c;
	__int128 Aa,Ab,Ac,Ba,Bb,Bc,Ca,Cb,Cc;
	long long int ans=0;
	map<pair<int,int>,long long int> ma,mb,mc;
	map<pair<int,int>,long long int>::iterator u,t;
	pair<int,int> temp;
	vector<pair<int,int>> va,vb,vc;
	scanf("%d%d%d",&a,&b,&c);
	for(int i=1;i<=a;i++){
		scanf("%d%d",&temp.F,&temp.S);
		va.PB(temp);
		ma[temp]++;
	}
	for(int i=1;i<=b;i++){
		scanf("%d%d",&temp.F,&temp.S);
		vb.PB(temp);
		mb[temp]++;
	}
	for(int i=1;i<=c;i++){
		scanf("%d%d",&temp.F,&temp.S);
		vc.PB(temp);
		mc[temp]++;
	}
	if(ma.size()==1)for(int i=1;i<=b;i++)ans+=mc[getmid(va[0],vb[i])]*a;
	else if(mb.size()==1)for(int i=1;i<=a;i++)ans+=mc[getmid(va[i],vb[0])]*b;
	else if(mc.size()==1)for(int i=1;i<=a;i++)ans+=mb[getnxt(va[i],vc[0])]*c;
	else{
		u=ma.begin(),t=ma.end();
		t--;
		Aa=u->F.S-t->F.S,Ba=t->F.F-u->F.F;
		Ca=Aa*(u->F.F)+Ba*(u->F.S);
		u=mb.begin(),t=mb.end();
		t--;
		Ab=u->F.S-t->F.S,Bb=t->F.F-u->F.F;
		Cb=Ab*(u->F.F)+Bb*(u->F.S);
		u=mc.begin(),t=mc.end();
		t--;
		Ac=u->F.S-t->F.S,Bc=t->F.F-u->F.F;
		Cc=Ac*(u->F.F)+Bc*(u->F.S);
		if(Aa==0){
			if(Ab==0){
				if(Ac==0){
					Ca/=Ba;
					Cb/=Bb;
					Cc/=Bc;
					if(Cc*2==Ca+Cb)ans=allsame(va,vb,vc);
					else ans=0;
				}
				else ans=ABsame(va,vb,vc);
			}
			else if(Ac==0)ans=ACsame(va,vb,vc);
			else if(Ab*Bc==Bb*Ac)ans=ACsame(vb,va,vc);
			else {
				for(pair<pair<int,int>,long long int> i:mb){
					temp=intersect(Aa,Ba,Ca,Ac,Bc,Cc*2-Ac*i.F.F-Bc*i.F.S);
					if(temp.F<N&&temp.S<N)ans+=ma[temp]*mc[getmid(temp,i.F)]*i.S;
				}
			}
		}
		else if(Ba==0){
			if(Bb==0){
				if(Bc==0){
					Ca/=Aa;
					Cb/=Ab;
					Cc/=Ac;
					if(Cc*2==Ca+Cb)ans=allsame(va,vb,vc);
					else ans=0;
				}
				else ans=ABsame(va,vb,vc);
			}
			else if(Bc==0)ans=ACsame(va,vb,vc);
			else if(Ab*Bc==Bb*Ac)ans=ACsame(vb,va,vc);
			else{
				for(pair<pair<int,int>,long long int> i:mb){
					temp=intersect(Aa,Ba,Ca,Ac,Bc,Cc*2-Ac*i.F.F-Bc*i.F.S);
					if(temp.F<N&&temp.S<N)ans+=ma[temp]*mc[getmid(temp,i.F)]*i.S;
				}
			}
		}
		else if(Ab==0){
			if(Ac==0)ans=ACsame(vb,va,vc);
			else if(Aa*Bc==Ac*Ba)ans=ACsame(va,vb,vc);
			else {
				for(pair<pair<int,int>,long long int> i:mb){
					temp=intersect(Aa,Ba,Ca,Ac,Bc,Cc*2-Ac*i.F.F-Bc*i.F.S);
					if(temp.F<N&&temp.S<N)ans+=ma[temp]*mc[getmid(temp,i.F)]*i.S;
				}
			}
		}
		else if(Bb==0){
			if(Bc==0)ans=ACsame(vb,va,vc);
			else if(Aa*Bc==Ac*Ba)ans=ACsame(va,vb,vc);
			else{
				for(pair<pair<int,int>,long long int> i:mb){
					temp=intersect(Aa,Ba,Ca,Ac,Bc,Cc*2-Ac*i.F.F-Bc*i.F.S);
					if(temp.F<N&&temp.S<N)ans+=ma[temp]*mc[getmid(temp,i.F)]*i.S;
				}
			}
		}
		else if(Aa*Bb==Ab*Ba){
			if(Ab*Bc==Bb*Ac){
				if(Cc*Ab*Aa*2==Ca*Ab*Ac+Cb*Aa*Ac)ans=allsame(va,vb,vc);
				else ans=0;
			}
			else ans=ABsame(va,vb,vc);
		}
		else if(Bb*Ac==Bc*Ab)ans=ACsame(vb,va,vc);
		else if(Aa*Bc==Ac*Ba)ans=ACsame(va,vb,vc);
		else{
			for(pair<pair<int,int>,long long int> i:mb){
				temp=intersect(Aa,Ba,Ca,Ac,Bc,Cc*2-Ac*i.F.F-Bc*i.F.S);
				if(temp.F<N&&temp.S<N)ans+=ma[temp]*mc[getmid(temp,i.F)]*i.S;
			}
		}
	}
	printf("%lld\n",ans);
}
accuracy: 0.5932203389830508
time_ms: 190
memory_kb: 37896
final_rank: 10

code_snippet: bool debug=false;
#include <algorithm>
#include <stdio.h>
#include <vector>
#include <utility>
#include <map>
#include <math.h>
using namespace std;
#define PB push_back
#define F first
#define S second
const int INF=1e9+10;
const int N=1e5+10;
const double pi=acos(-1);
pair<int,int> getmid(pair<int,int> a,pair<int,int> b){
	if(((a.F+b.F)&1)||((a.S+b.S)&1))return {INF,INF};
	return {(a.F+b.F)>>1,(a.S+b.S)>>1};
}
pair<int,int> getnxt(pair<int,int> a,pair<int,int> c){
	return {(c.F-a.F)*2+a.F,(c.S-a.S)*2+a.S};
}
__int128 myabs(__int128 x){return x>0?x:-x;}
pair<int,int> intersect(__int128 Aa,__int128 Ba,__int128 Ca,__int128 Ab,__int128 Bb,__int128 Cb){
	__int128 x=Ba*Cb-Bb*Ca,y=Ca*Ab-Cb*Aa,det=Ba*Ab-Aa*Bb;
	if(x%det!=0)return {INF,INF};
	if(y%det!=0)return {INF,INF};
	x/=det;
	y/=det;
	if(myabs(x)>N)return {INF,INF};
	if(myabs(y)>N)return {INF,INF};
	return {x,y};
}
pair<double,double> mul(pair<double,double> a,pair<double,double> b){
	return {a.F*b.F-a.S*b.S,a.F*b.S+a.S*b.F};
}
void fft(vector<pair<double,double>>& v,int size,bool on){
    pair<double,double> wn,u,t,w,inv;
	for(int i=1,j=size>>1,k;i<(size-1);i++){
        if(i<j)swap(v[i],v[j]);
        k=size>>1;
        while(j&k){
            j^=k;
            k>>=1;
        }
        j|=k;
    }
    for(int i=2;i<=size;i<<=1){
        wn={cos(2*pi/i),sin(2*pi/i)};
		if(on)wn.S=-wn.S;
        for(int j=0;j<size;j+=i){
            w={1,0};
            for(int k=j;k<j+(i>>1);k++){
                u=v[k];
                t=mul(w,v[k+(i>>1)]);
                v[k]={u.F+t.F,u.S+t.S};
                v[k+(i>>1)]={u.F-t.F,u.S-t.S};
                w=mul(wn,w);
            }
        }
    }
    if(on){
        inv={1.0/size,0};
        for(int i=0;i<size;i++)v[i]=mul(v[i],inv);
    }
    return ;
}
long long int allsame(vector<pair<int,int>>&va,vector<pair<int,int>>&vb,vector<pair<int,int>>&vc){
	vector<pair<double,double>> a,b;
	vector<long long int> c;
	long long int ans=0;
	int n=N<<2,sz=1;
	while(sz<n)sz<<=1;
	a.resize(sz,{0,0});
	b.resize(sz,{0,0});
	c.resize(sz>>1,0);
	if(va[0].F==va.back().F){
		for(pair<int,int> i:va)a[i.S+N].F+=1;
		for(pair<int,int> i:vb)b[i.S+N].F+=1;
		for(pair<int,int> i:vc)c[i.S+N]++;
	}
	else{
		for(pair<int,int> i:va)a[i.F+N].F+=1;
		for(pair<int,int> i:vb)b[i.F+N].F+=1;
		for(pair<int,int> i:vc)c[i.F+N]++;
	}
	if(debug){
		printf("a::\n");for(int i=0;i<sz;i++)if(a[i].F>0)printf("%d::(%.2lf,%.2lf)\n",i,a[i].F,a[i].S);
		printf("b::\n");for(int i=0;i<sz;i++)if(b[i].F>0)printf("%d::(%.2lf,%.2lf)\n",i,b[i].F,b[i].S);
	}
	fft(a,sz,0);
	fft(b,sz,0);
	for(int i=0;i<a.size();i++)a[i]=mul(a[i],b[i]);
	fft(a,sz,1);
	if(debug){
		printf("after::\n");for(int i=0;i<sz;i++)if(a[i].F>0)printf("%d::(%.2lf,%.2lf)\n",i,a[i].F,a[i].S);
		printf("c::\n");for(int i=0;i<(sz>>1);i++)if(c[i]>0)printf("%d::%d\n",i,c[i]);
	}
	for(int i=0;i<(sz>>1);i++)ans+=c[i]*((long long int)(a[i<<1].F+0.5));
	return ans;
}
long long int ABsame(vector<pair<int,int>>&va,vector<pair<int,int>>&vb,vector<pair<int,int>>&vc){
	vector<pair<double,double>> a,b;
	int n=N<<2,sz=1;
	pair<int,int> temp;
	long long int Aa,Ba,Ca,Cb,Ac,Bc,Cc;
	while(sz<n)sz<<=1;
	a.resize(sz,{0,0});
	b.resize(sz,{0,0});
	if(va[0].F==va.back().F){
		for(pair<int,int> i:va)a[i.S+N].F+=1;
		for(pair<int,int> i:vb)b[i.S+N].F+=1;
	}
	else{
		for(pair<int,int> i:va)a[i.F+N].F+=1;
		for(pair<int,int> i:vb)b[i.F+N].F+=1;
	}
	fft(a,sz,0);
	fft(b,sz,0);
	for(int i=0;i<a.size();i++)a[i]=mul(a[i],b[i]);
	fft(a,sz,1);
	Aa=va[0].S-va.back().S,Ba=va.back().F-va[0].F;
	Ca=Aa*va[0].F+Ba*va[0].S;
	Cb=Aa*vb[0].F+Ba*vb[0].S;
	Ac=vc[0].S-vc.back().S,Bc=vc.back().F-vc[0].F;
	Cc=Ac*vc[0].F+Bc*vc[0].S;
	temp=intersect(Aa*2,Ba*2,Ca+Cb,Ac,Bc,Cc);
	if(va[0].F==va.back().F)return ((long long int)(a[(temp.S+N)<<1].F+0.5))*(upper_bound(vc.begin(),vc.end(),temp)-lower_bound(vc.begin(),vc.end(),temp));
	else return ((long long int)(a[(temp.S+N)<<1].F+0.5))*(upper_bound(vc.begin(),vc.end(),temp)-lower_bound(vc.begin(),vc.end(),temp));
}
long long int ACsame(vector<pair<int,int>>&va,vector<pair<int,int>>&vb,vector<pair<int,int>>&vc){
	vector<pair<double,double>>a,b;
	vector<long long int> c;
	int n=N<<2,sz=1;
	long long int ans=0,Aa,Ba,Ca,Ab,Bb,Cb,Cc;
	pair<int,int> temp;
	while(sz<n)sz<<=1;
	a.resize(sz,{0,0});
	b.resize(sz,{0,0});
	c.resize(sz>>1,0);
	Aa=va[0].S-va.back().S,Ba=va.back().F-va[0].F;
	Ca=Aa*va[0].F+Ba*va[0].S;
	Cc=Aa*vc[0].F+Ba*vc[0].S;
	Ab=vb[0].S-vb.back().S,Bb=vb.back().F-vb[0].F;
	Cb=Ab*vb[0].F+Bb*vb[0].S;
	temp=intersect(Aa,Ba,Cc*2-Ca,Ab,Bb,Cb);
	if(va[0].F==va.back().F){
		for(pair<int,int> i:va)a[i.S+N].F+=1;
		for(pair<int,int> i:vc)c[i.S+N]++;
		b[temp.S+N].F=upper_bound(vb.begin(),vb.end(),temp)-lower_bound(vb.begin(),vb.end(),temp);
	}
	else{
		for(pair<int,int> i:va)a[i.F+N].F+=1;
		for(pair<int,int> i:vc)c[i.F+N]++;
		b[temp.F+N].F=upper_bound(vb.begin(),vb.end(),temp)-lower_bound(vb.begin(),vb.end(),temp);
	}
	fft(a,sz,0);
	fft(b,sz,0);
	for(int i=0;i<sz;i++)a[i]=mul(a[i],b[i]);
	fft(a,sz,1);
	for(int i=0;i<(sz>>1);i++)ans+=c[i]*((long long int)(a[i<<1].F+0.5));
	return ans;
}
int main(){
	int a,b,c;
	__int128 Aa,Ab,Ac,Ba,Bb,Bc,Ca,Cb,Cc;
	long long int ans=0;
	map<pair<int,int>,long long int> ma,mb,mc;
	map<pair<int,int>,long long int>::iterator u,t;
	pair<int,int> temp;
	vector<pair<int,int>> va,vb,vc;
	scanf("%d%d%d",&a,&b,&c);
	for(int i=1;i<=a;i++){
		scanf("%d%d",&temp.F,&temp.S);
		va.PB(temp);
		ma[temp]++;
	}
	for(int i=1;i<=b;i++){
		scanf("%d%d",&temp.F,&temp.S);
		vb.PB(temp);
		mb[temp]++;
	}
	for(int i=1;i<=c;i++){
		scanf("%d%d",&temp.F,&temp.S);
		vc.PB(temp);
		mc[temp]++;
	}
	if(ma.size()==1)for(int i=1;i<=b;i++)ans+=mc[getmid(va[0],vb[i])]*a;
	else if(mb.size()==1)for(int i=1;i<=a;i++)ans+=mc[getmid(va[i],vb[0])]*b;
	else if(mc.size()==1)for(int i=1;i<=a;i++)ans+=mb[getnxt(va[i],vc[0])]*c;
	else{
		u=ma.begin(),t=ma.end();
		t--;
		Aa=u->F.S-t->F.S,Ba=t->F.F-u->F.F;
		Ca=Aa*(u->F.F)+Ba*(u->F.S);
		u=mb.begin(),t=mb.end();
		t--;
		Ab=u->F.S-t->F.S,Bb=t->F.F-u->F.F;
		Cb=Ab*(u->F.F)+Bb*(u->F.S);
		u=mc.begin(),t=mc.end();
		t--;
		Ac=u->F.S-t->F.S,Bc=t->F.F-u->F.F;
		Cc=Ac*(u->F.F)+Bc*(u->F.S);
		if(Aa==0){
			if(Ab==0){
				if(Ac==0){
					Ca/=Ba;
					Cb/=Bb;
					Cc/=Bc;
					if(Cc*2==Ca+Cb)ans=allsame(va,vb,vc);
					else ans=0;
				}
				else ans=ABsame(va,vb,vc);
			}
			else if(Ac==0)ans=ACsame(va,vb,vc);
			else if(Ab*Bc==Bb*Ac)ans=ACsame(vb,va,vc);
			else {
				for(pair<pair<int,int>,long long int> i:mb){
					temp=intersect(Aa,Ba,Ca,Ac,Bc,Cc*2-Ac*i.F.F-Bc*i.F.S);
					ans+=ma[temp]*mc[getmid(temp,i.F)]*i.S;
				}
			}
		}
		else if(Ba==0){
			if(Bb==0){
				if(Bc==0){
					Ca/=Aa;
					Cb/=Ab;
					Cc/=Ac;
					if(Cc*2==Ca+Cb)ans=allsame(va,vb,vc);
					else ans=0;
				}
				else ans=ABsame(va,vb,vc);
			}
			else if(Bc==0)ans=ACsame(va,vb,vc);
			else if(Ab*Bc==Bb*Ac)ans=ACsame(vb,va,vc);
			else{
				for(pair<pair<int,int>,long long int> i:mb){
					temp=intersect(Aa,Ba,Ca,Ac,Bc,Cc*2-Ac*i.F.F-Bc*i.F.S);
					ans+=ma[temp]*mc[getmid(temp,i.F)]*i.S;
				}
			}
		}
		else if(Ab==0){
			if(Ac==0)ans=ACsame(vb,va,vc);
			else if(Aa*Bc==Ac*Ba)ans=ACsame(va,vb,vc);
			else {
				for(pair<pair<int,int>,long long int> i:mb){
					temp=intersect(Aa,Ba,Ca,Ac,Bc,Cc*2-Ac*i.F.F-Bc*i.F.S);
					ans+=ma[temp]*mc[getmid(temp,i.F)]*i.S;
				}
			}
		}
		else if(Bb==0){
			if(Bc==0)ans=ACsame(vb,va,vc);
			else if(Aa*Bc==Ac*Ba)ans=ACsame(va,vb,vc);
			else{
				for(pair<pair<int,int>,long long int> i:mb){
					temp=intersect(Aa,Ba,Ca,Ac,Bc,Cc*2-Ac*i.F.F-Bc*i.F.S);
					ans+=ma[temp]*mc[getmid(temp,i.F)]*i.S;
				}
			}
		}
		else if(Aa*Bb==Ab*Ba){
			if(Ab*Bc==Bb*Ac){
				if(Cc*Ab*Aa*2==Ca*Ab*Ac+Cb*Aa*Ac)ans=allsame(va,vb,vc);
				else ans=0;
			}
			else ans=ABsame(va,vb,vc);
		}
		else if(Bb*Ac==Bc*Ab)ans=ACsame(vb,va,vc);
		else if(Aa*Bc==Ac*Ba)ans=ACsame(va,vb,vc);
		else{
			for(pair<pair<int,int>,long long int> i:mb){
				temp=intersect(Aa,Ba,Ca,Ac,Bc,Cc*2-Ac*i.F.F-Bc*i.F.S);
				ans+=ma[temp]*mc[getmid(temp,i.F)]*i.S;
			}
		}
	}
	printf("%lld\n",ans);
}
accuracy: 0.5932203389830508
time_ms: 180
memory_kb: 37924
final_rank: 9

code_snippet: bool debug=false;
#include <algorithm>
#include <stdio.h>
#include <vector>
#include <utility>
#include <map>
#include <math.h>
using namespace std;
#define PB push_back
#define F first
#define S second
const int INF=1e9+10;
const int N=1e5+10;
const double pi=acos(-1);
pair<int,int> getmid(pair<int,int> a,pair<int,int> b){
	if(((a.F+b.F)&1)||((a.S+b.S)&1))return {INF,INF};
	return {(a.F+b.F)>>1,(a.S+b.S)>>1};
}
pair<int,int> getnxt(pair<int,int> a,pair<int,int> c){
	return {(c.F-a.F)*2+a.F,(c.S-a.S)*2+a.S};
}
__int128 myabs(__int128 x){return x>0?x:-x;}
pair<int,int> intersect(__int128 Aa,__int128 Ba,__int128 Ca,__int128 Ab,__int128 Bb,__int128 Cb){
	__int128 x=Ba*Cb-Bb*Ca,y=Ca*Ab-Cb*Aa,det=Ba*Ab-Aa*Bb;
	if(x%det!=0)return {INF,INF};
	if(y%det!=0)return {INF,INF};
	x/=det;
	y/=det;
	if(myabs(x)>N)return {INF,INF};
	if(myabs(y)>N)return {INF,INF};
	return {x,y};
}
pair<double,double> mul(pair<double,double> a,pair<double,double> b){
	return {a.F*b.F-a.S*b.S,a.F*b.S+a.S*b.F};
}
void fft(vector<pair<double,double>>& v,int size,bool on){
    pair<double,double> wn,u,t,w,inv;
	for(int i=1,j=size>>1,k;i<(size-1);i++){
        if(i<j)swap(v[i],v[j]);
        k=size>>1;
        while(j&k){
            j^=k;
            k>>=1;
        }
        j|=k;
    }
    for(int i=2;i<=size;i<<=1){
        wn={cos(2*pi/i),sin(2*pi/i)};
		if(on)wn.S=-wn.S;
        for(int j=0;j<size;j+=i){
            w={1,0};
            for(int k=j;k<j+(i>>1);k++){
                u=v[k];
                t=mul(w,v[k+(i>>1)]);
                v[k]={u.F+t.F,u.S+t.S};
                v[k+(i>>1)]={u.F-t.F,u.S-t.S};
                w=mul(wn,w);
            }
        }
    }
    if(on){
        inv={1.0/size,0};
        for(int i=0;i<size;i++)v[i]=mul(v[i],inv);
    }
    return ;
}
long long int allsame(vector<pair<int,int>>&va,vector<pair<int,int>>&vb,vector<pair<int,int>>&vc){
	vector<pair<double,double>> a,b;
	vector<long long int> c;
	long long int ans=0;
	int n=N<<2,sz=1;
	while(sz<n)sz<<=1;
	a.resize(sz,{0,0});
	b.resize(sz,{0,0});
	c.resize(sz>>1,0);
	if(va[0].F==va.back().F){
		for(pair<int,int> i:va)a[i.S+N].F+=1;
		for(pair<int,int> i:vb)b[i.S+N].F+=1;
		for(pair<int,int> i:vc)c[i.S+N]++;
	}
	else{
		for(pair<int,int> i:va)a[i.F+N].F+=1;
		for(pair<int,int> i:vb)b[i.F+N].F+=1;
		for(pair<int,int> i:vc)c[i.F+N]++;
	}
	if(debug){
		printf("a::\n");for(int i=0;i<sz;i++)if(a[i].F>0)printf("%d::(%.2lf,%.2lf)\n",i,a[i].F,a[i].S);
		printf("b::\n");for(int i=0;i<sz;i++)if(b[i].F>0)printf("%d::(%.2lf,%.2lf)\n",i,b[i].F,b[i].S);
	}
	fft(a,sz,0);
	fft(b,sz,0);
	for(int i=0;i<a.size();i++)a[i]=mul(a[i],b[i]);
	fft(a,sz,1);
	if(debug){
		printf("after::\n");for(int i=0;i<sz;i++)if(a[i].F>0)printf("%d::(%.2lf,%.2lf)\n",i,a[i].F,a[i].S);
		printf("c::\n");for(int i=0;i<(sz>>1);i++)if(c[i]>0)printf("%d::%d\n",i,c[i]);
	}
	for(int i=0;i<(sz>>1);i++)ans+=c[i]*((long long int)(a[i<<1].F+0.5));
	return ans;
}
long long int ABsame(vector<pair<int,int>>&va,vector<pair<int,int>>&vb,vector<pair<int,int>>&vc){
	vector<pair<double,double>> a,b;
	int n=N<<2,sz=1;
	pair<int,int> temp;
	long long int Aa,Ba,Ca,Cb,Ac,Bc,Cc;
	while(sz<n)sz<<=1;
	a.resize(sz,{0,0});
	b.resize(sz,{0,0});
	if(va[0].F==va.back().F){
		for(pair<int,int> i:va)a[i.S+N].F+=1;
		for(pair<int,int> i:vb)b[i.S+N].F+=1;
	}
	else{
		for(pair<int,int> i:va)a[i.F+N].F+=1;
		for(pair<int,int> i:vb)b[i.F+N].F+=1;
	}
	fft(a,sz,0);
	fft(b,sz,0);
	for(int i=0;i<a.size();i++)a[i]=mul(a[i],b[i]);
	fft(a,sz,1);
	Aa=va[0].S-va.back().S,Ba=va.back().F-va[0].F;
	Ca=Aa*va[0].F+Ba*va[0].S;
	Cb=Aa*vb[0].F+Ba*vb[0].S;
	Ac=vc[0].S-vc.back().S,Bc=vc.back().F-vc[0].F;
	Cc=Ac*vc[0].F+Bc*vc[0].S;
	temp=intersect(Aa*2,Ba*2,Ca+Cb,Ac,Bc,Cc);
	if(va[0].F==va.back().F)return ((long long int)(a[(temp.S+N)<<1].F+0.5))*(upper_bound(vc.begin(),vc.end(),temp)-lower_bound(vc.begin(),vc.end(),temp));
	else return ((long long int)(a[(temp.S+N)<<1].F+0.5))*(upper_bound(vc.begin(),vc.end(),temp)-lower_bound(vc.begin(),vc.end(),temp));
}
long long int ACsame(vector<pair<int,int>>&va,vector<pair<int,int>>&vb,vector<pair<int,int>>&vc){
	vector<pair<double,double>>a,b;
	vector<long long int> c;
	int n=N<<2,sz=1;
	long long int ans=0,Aa,Ba,Ca,Ab,Bb,Cb,Cc;
	pair<int,int> temp;
	while(sz<n)sz<<=1;
	a.resize(sz,{0,0});
	b.resize(sz,{0,0});
	c.resize(sz>>1,0);
	Aa=va[0].S-va.back().S,Ba=va.back().F-va[0].F;
	Ca=Aa*va[0].F+Ba*va[0].S;
	Cc=Aa*vc[0].F+Ba*vc[0].S;
	Ab=vb[0].S-vb.back().S,Bb=vb.back().F-vb[0].F;
	Cb=Ab*vb[0].F+Bb*vb[0].S;
	temp=intersect(Aa,Ba,Cc*2-Ca,Ab,Bb,Cb);
	if(va[0].F==va.back().F){
		for(pair<int,int> i:va)a[i.S+N].F+=1;
		for(pair<int,int> i:vc)c[i.S+N]++;
		b[temp.S+N].F=upper_bound(vb.begin(),vb.end(),temp)-lower_bound(vb.begin(),vb.end(),temp);
	}
	else{
		for(pair<int,int> i:va)a[i.F+N].F+=1;
		for(pair<int,int> i:vc)c[i.F+N]++;
		b[temp.F+N].F=upper_bound(vb.begin(),vb.end(),temp)-lower_bound(vb.begin(),vb.end(),temp);
	}
	fft(a,sz,0);
	fft(b,sz,0);
	for(int i=0;i<sz;i++)a[i]=mul(a[i],b[i]);
	fft(a,sz,1);
	for(int i=0;i<(sz>>1);i++)ans+=c[i]*((long long int)(a[i<<1].F+0.5));
	return ans;
}
int main(){
	int a,b,c;
	__int128 Aa,Ab,Ac,Ba,Bb,Bc,Ca,Cb,Cc;
	long long int ans=0;
	map<pair<int,int>,long long int> ma,mb,mc;
	map<pair<int,int>,long long int>::iterator u,t;
	pair<int,int> temp;
	vector<pair<int,int>> va,vb,vc;
	scanf("%d%d%d",&a,&b,&c);
	for(int i=1;i<=a;i++){
		scanf("%d%d",&temp.F,&temp.S);
		va.PB(temp);
		ma[temp]++;
	}
	for(int i=1;i<=b;i++){
		scanf("%d%d",&temp.F,&temp.S);
		vb.PB(temp);
		mb[temp]++;
	}
	for(int i=1;i<=c;i++){
		scanf("%d%d",&temp.F,&temp.S);
		vc.PB(temp);
		mc[temp]++;
	}
	if(ma.size()==1)for(int i=1;i<=b;i++)ans+=mc[getmid(va[0],vb[i])]*a;
	else if(mb.size()==1)for(int i=1;i<=a;i++)ans+=mc[getmid(va[i],vb[0])]*b;
	else if(mc.size()==1)for(int i=1;i<=a;i++)ans+=mb[getnxt(va[i],vc[0])]*c;
	else{
		u=ma.begin(),t=ma.end();
		t--;
		Aa=u->F.S-t->F.S,Ba=t->F.F-u->F.F;
		Ca=Aa*(u->F.F)+Ba*(u->F.S);
		u=mb.begin(),t=mb.end();
		t--;
		Ab=u->F.S-t->F.S,Bb=t->F.F-u->F.F;
		Cb=Ab*(u->F.F)+Bb*(u->F.S);
		u=mc.begin(),t=mc.end();
		t--;
		Ac=u->F.S-t->F.S,Bc=t->F.F-u->F.F;
		Cc=Ac*(u->F.F)+Bc*(u->F.S);
		if(Aa==0){
			if(Ab==0){
				if(Ac==0){
					Ca/=Ba;
					Cb/=Bb;
					Cc/=Bc;
					if(Cc*2==Ca+Cb)ans=allsame(va,vb,vc);
					else ans=0;
				}
				else ans=ABsame(va,vb,vc);
			}
			else if(Ac==0)ans=ACsame(va,vb,vc);
			else if(Ab*Bc==Bb*Ac)ans=ACsame(vb,va,vc);
			else {
				for(pair<pair<int,int>,long long int> i:mb){
					temp=intersect(Aa,Ba,Ca,Ac,Bc,Cc*2-Ac*i.F.F-Bc*i.F.S);
					ans+=ma[temp]*mc[getmid(temp,i.F)]*i.S;
				}
			}
		}
		else if(Ba==0){
			if(Bb==0){
				if(Bc==0){
					Ca/=Aa;
					Cb/=Ab;
					Cc/=Ac;
					if(Cc*2==Ca+Cb)ans=allsame(va,vb,vc);
					else ans=0;
				}
				else ans=ABsame(va,vb,vc);
			}
			else if(Bc==0)ans=ACsame(va,vb,vc);
			else if(Ab*Bc==Bb*Ac)ans=ACsame(vb,va,vc);
			else{
				for(pair<pair<int,int>,long long int> i:mb){
					temp=intersect(Aa,Ba,Ca,Ac,Bc,Cc*2-Ac*i.F.F-Bc*i.F.S);
					ans+=ma[temp]*mc[getmid(temp,i.F)]*i.S;
				}
			}
		}
		else if(Ab==0){
			if(Ac==0)ans=ACsame(vb,va,vc);
			else if(Aa*Bc==Ac*Ba)ans=ACsame(va,vb,vc);
			else {
				for(pair<pair<int,int>,long long int> i:mb){
					temp=intersect(Aa,Ba,Ca,Ac,Bc,Cc*2-Ac*i.F.F-Bc*i.F.S);
					ans+=ma[temp]*mc[getmid(temp,i.F)]*i.S;
				}
			}
		}
		else if(Bb==0){
			if(Bc==0)ans=ACsame(vb,va,vc);
			else if(Aa*Bc==Ac*Ba)ans=ACsame(va,vb,vc);
			else{
				for(pair<pair<int,int>,long long int> i:mb){
					temp=intersect(Aa,Ba,Ca,Ac,Bc,Cc*2-Ac*i.F.F-Bc*i.F.S);
					ans+=ma[temp]*mc[getmid(temp,i.F)]*i.S;
				}
			}
		}
		else if(Aa*Bb==Ab*Ba){
			if(Ab*Bc==Bb*Ac){
				if(Cc*Ac*2==Ca*Aa+Cb*Ab)ans=allsame(va,vb,vc);
				else ans=0;
			}
			else ans=ABsame(va,vb,vc);
		}
		else if(Bb*Ac==Bc*Ab)ans=ACsame(vb,va,vc);
		else if(Aa*Bc==Ac*Ba)ans=ACsame(va,vb,vc);
		else{
			for(pair<pair<int,int>,long long int> i:mb){
				temp=intersect(Aa,Ba,Ca,Ac,Bc,Cc*2-Ac*i.F.F-Bc*i.F.S);
				ans+=ma[temp]*mc[getmid(temp,i.F)]*i.S;
			}
		}
	}
	printf("%lld\n",ans);
}
accuracy: 0.3220338983050847
time_ms: 130
memory_kb: 20832
final_rank: 17

code_snippet: bool debug=false;
#include <algorithm>
#include <stdio.h>
#include <vector>
#include <utility>
#include <map>
#include <math.h>
using namespace std;
#define PB push_back
#define F first
#define S second
const int INF=1e9+10;
const int N=1e5+10;
const double pi=acos(-1);
pair<int,int> getmid(pair<int,int> a,pair<int,int> b){
	if(((a.F+b.F)&1)||((a.S+b.S)&1))return {INF,INF};
	return {(a.F+b.F)>>1,(a.S+b.S)>>1};
}
pair<int,int> getnxt(pair<int,int> a,pair<int,int> c){
	return {(c.F-a.F)*2+a.F,(c.S-a.S)*2+a.S};
}
__int128 myabs(__int128 x){return x>0?x:-x;}
pair<int,int> intersect(__int128 Aa,__int128 Ba,__int128 Ca,__int128 Ab,__int128 Bb,__int128 Cb){
	__int128 x=Ba*Cb-Bb*Ca,y=Ca*Ab-Cb*Aa,det=Ba*Ab-Aa*Bb;
	if(x%det!=0)return {INF,INF};
	if(y%det!=0)return {INF,INF};
	x/=det;
	y/=det;
	if(myabs(x)>N)return {INF,INF};
	if(myabs(y)>N)return {INF,INF};
	return {x,y};
}
pair<double,double> mul(pair<double,double> a,pair<double,double> b){
	return {a.F*b.F-a.S*b.S,a.F*b.S+a.S*b.F};
}
void fft(vector<pair<double,double>>& v,int size,bool on){
    pair<double,double> wn,u,t,w,inv;
	for(int i=1,j=size>>1,k;i<(size-1);i++){
        if(i<j)swap(v[i],v[j]);
        k=size>>1;
        while(j&k){
            j^=k;
            k>>=1;
        }
        j|=k;
    }
    for(int i=2;i<=size;i<<=1){
        wn={cos(2*pi/i),sin(2*pi/i)};
		if(on)wn.S=-wn.S;
        for(int j=0;j<size;j+=i){
            w={1,0};
            for(int k=j;k<j+(i>>1);k++){
                u=v[k];
                t=mul(w,v[k+(i>>1)]);
                v[k]={u.F+t.F,u.S+t.S};
                v[k+(i>>1)]={u.F-t.F,u.S-t.S};
                w=mul(wn,w);
            }
        }
    }
    if(on){
        inv={1.0/size,0};
        for(int i=0;i<size;i++)v[i]=mul(v[i],inv);
    }
    return ;
}
long long int allsame(vector<pair<int,int>>&va,vector<pair<int,int>>&vb,vector<pair<int,int>>&vc){
	vector<pair<double,double>> a,b;
	vector<long long int> c;
	long long int ans=0;
	int n=N<<2,sz=1;
	while(sz<n)sz<<=1;
	a.resize(sz,{0,0});
	b.resize(sz,{0,0});
	c.resize(sz>>1,0);
	if(va[0].F==va.back().F){
		for(pair<int,int> i:va)a[i.S+N].F+=1;
		for(pair<int,int> i:vb)b[i.S+N].F+=1;
		for(pair<int,int> i:vc)c[i.S+N]++;
	}
	else{
		for(pair<int,int> i:va)a[i.F+N].F+=1;
		for(pair<int,int> i:vb)b[i.F+N].F+=1;
		for(pair<int,int> i:vc)c[i.F+N]++;
	}
	if(debug){
		printf("a::\n");for(int i=0;i<sz;i++)if(a[i].F>0)printf("%d::(%.2lf,%.2lf)\n",i,a[i].F,a[i].S);
		printf("b::\n");for(int i=0;i<sz;i++)if(b[i].F>0)printf("%d::(%.2lf,%.2lf)\n",i,b[i].F,b[i].S);
	}
	fft(a,sz,0);
	fft(b,sz,0);
	for(int i=0;i<a.size();i++)a[i]=mul(a[i],b[i]);
	fft(a,sz,1);
	if(debug){
		printf("after::\n");for(int i=0;i<sz;i++)if(a[i].F>0)printf("%d::(%.2lf,%.2lf)\n",i,a[i].F,a[i].S);
		printf("c::\n");for(int i=0;i<(sz>>1);i++)if(c[i]>0)printf("%d::%d\n",i,c[i]);
	}
	for(int i=0;i<(sz>>1);i++)ans+=c[i]*((long long int)(a[i<<1].F+0.5));
	return ans;
}
long long int ABsame(vector<pair<int,int>>&va,vector<pair<int,int>>&vb,vector<pair<int,int>>&vc){
	vector<pair<double,double>> a,b;
	int n=N<<2,sz=1;
	pair<int,int> temp;
	long long int Aa,Ba,Ca,Cb,Ac,Bc,Cc;
	while(sz<n)sz<<=1;
	a.resize(sz,{0,0});
	b.resize(sz,{0,0});
	if(va[0].F==va.back().F){
		for(pair<int,int> i:va)a[i.S+N].F+=1;
		for(pair<int,int> i:vb)b[i.S+N].F+=1;
	}
	else{
		for(pair<int,int> i:va)a[i.F+N].F+=1;
		for(pair<int,int> i:vb)b[i.F+N].F+=1;
	}
	fft(a,sz,0);
	fft(b,sz,0);
	for(int i=0;i<a.size();i++)a[i]=mul(a[i],b[i]);
	fft(a,sz,1);
	Aa=va[0].S-va.back().S,Ba=va.back().F-va[0].F;
	Ca=Aa*va[0].F+Ba*va[0].S;
	Cb=Aa*vb[0].F+Ba*vb[0].S;
	Ac=vc[0].S-vc.back().S,Bc=vc.back().F-vc[0].F;
	Cc=Ac*vc[0].F+Bc*vc[0].S;
	temp=intersect(Aa*2,Ba*2,Ca+Cb,Ac,Bc,Cc);
	if(va[0].F==va.back().F)return ((long long int)(a[(temp.S+N)<<1].F+0.5))*(upper_bound(vc.begin(),vc.end(),temp)-lower_bound(vc.begin(),vc.end(),temp));
	else return ((long long int)(a[(temp.S+N)<<1].F+0.5))*(upper_bound(vc.begin(),vc.end(),temp)-lower_bound(vc.begin(),vc.end(),temp));
}
long long int ACsame(vector<pair<int,int>>&va,vector<pair<int,int>>&vb,vector<pair<int,int>>&vc){
	vector<pair<double,double>>a,b;
	vector<long long int> c;
	int n=N<<2,sz=1;
	long long int ans=0,Aa,Ba,Ca,Ab,Bb,Cb,Cc;
	pair<int,int> temp;
	while(sz<n)sz<<=1;
	a.resize(sz,{0,0});
	b.resize(sz,{0,0});
	c.resize(sz>>1,0);
	Aa=va[0].S-va.back().S,Ba=va.back().F-va[0].F;
	Ca=Aa*va[0].F+Ba*va[0].S;
	Cc=Aa*vc[0].F+Ba*vc[0].S;
	Ab=vb[0].S-vb.back().S,Bb=vb.back().F-vb[0].F;
	Cb=Ab*vb[0].F+Bb*vb[0].S;
	temp=intersect(Aa,Ba,Cc*2-Ca,Ab,Bb,Cb);
	if(va[0].F==va.back().F){
		for(pair<int,int> i:va)a[i.S+N].F+=1;
		for(pair<int,int> i:vc)c[i.S+N]++;
		b[temp.S+N].F=upper_bound(vb.begin(),vb.end(),temp)-lower_bound(vb.begin(),vb.end(),temp);
	}
	else{
		for(pair<int,int> i:va)a[i.F+N].F+=1;
		for(pair<int,int> i:vc)c[i.F+N]++;
		b[temp.F+N].F=upper_bound(vb.begin(),vb.end(),temp)-lower_bound(vb.begin(),vb.end(),temp);
	}
	fft(a,sz,0);
	fft(b,sz,0);
	for(int i=0;i<sz;i++)a[i]=mul(a[i],b[i]);
	fft(a,sz,1);
	for(int i=0;i<(sz>>1);i++)ans+=c[i]*((long long int)(a[i<<1].F+0.5));
	return ans;
}
int main(){
	int a,b,c;
	__int128 Aa,Ab,Ac,Ba,Bb,Bc,Ca,Cb,Cc;
	long long int ans=0;
	map<pair<int,int>,int> ma,mb,mc;
	map<pair<int,int>,int>::iterator u,t;
	pair<int,int> temp;
	vector<pair<int,int>> va,vb,vc;
	scanf("%d%d%d",&a,&b,&c);
	for(int i=1;i<=a;i++){
		scanf("%d%d",&temp.F,&temp.S);
		va.PB(temp);
		ma[temp]++;
	}
	for(int i=1;i<=b;i++){
		scanf("%d%d",&temp.F,&temp.S);
		vb.PB(temp);
		mb[temp]++;
	}
	for(int i=1;i<=c;i++){
		scanf("%d%d",&temp.F,&temp.S);
		vc.PB(temp);
		mc[temp]++;
	}
	if(ma.size()==1)for(int i=1;i<=b;i++)ans+=mc[getmid(va[0],vb[i])]*a;
	else if(mb.size()==1)for(int i=1;i<=a;i++)ans+=mc[getmid(va[i],vb[0])]*b;
	else if(mc.size()==1)for(int i=1;i<=a;i++)ans+=mb[getnxt(va[i],vc[0])]*c;
	else{
		u=ma.begin(),t=ma.end();
		t--;
		Aa=u->F.S-t->F.S,Ba=t->F.F-u->F.F;
		Ca=Aa*(u->F.F)+Ba*(u->F.S);
		u=mb.begin(),t=mb.end();
		t--;
		Ab=u->F.S-t->F.S,Bb=t->F.F-u->F.F;
		Cb=Ab*(u->F.F)+Bb*(u->F.S);
		u=mc.begin(),t=mc.end();
		t--;
		Ac=u->F.S-t->F.S,Bc=t->F.F-u->F.F;
		Cc=Ac*(u->F.F)+Bc*(u->F.S);
		if(Aa==0){
			if(Ab==0){
				if(Ac==0){
					Ca/=Ba;
					Cb/=Bb;
					Cc/=Bc;
					if(Cc*2==Ca+Cb)ans=allsame(va,vb,vc);
					else ans=0;
				}
				else ans=ABsame(va,vb,vc);
			}
			else if(Ac==0)ans=ACsame(va,vb,vc);
			else if(Ab*Bc==Bb*Ac)ans=ACsame(vb,va,vc);
			else {
				for(pair<pair<int,int>,int> i:mb){
					temp=intersect(Aa,Ba,Ca,Ac,Bc,Cc*2-Ac*i.F.F-Bc*i.F.S);
					ans+=ma[temp]*mc[getmid(temp,i.F)]*i.S;
				}
			}
		}
		else if(Ba==0){
			if(Bb==0){
				if(Bc==0){
					Ca/=Aa;
					Cb/=Ab;
					Cc/=Ac;
					if(Cc*2==Ca+Cb)ans=allsame(va,vb,vc);
					else ans=0;
				}
				else ans=ABsame(va,vb,vc);
			}
			else if(Bc==0)ans=ACsame(va,vb,vc);
			else if(Ab*Bc==Bb*Ac)ans=ACsame(vb,va,vc);
			else{
				for(pair<pair<int,int>,int> i:mb){
					temp=intersect(Aa,Ba,Ca,Ac,Bc,Cc*2-Ac*i.F.F-Bc*i.F.S);
					ans+=ma[temp]*mc[getmid(temp,i.F)]*i.S;
				}
			}
		}
		else if(Ab==0){
			if(Ac==0)ans=ACsame(vb,va,vc);
			else if(Aa*Bc==Ac*Ba)ans=ACsame(va,vb,vc);
			else {
				for(pair<pair<int,int>,int> i:mb){
					temp=intersect(Aa,Ba,Ca,Ac,Bc,Cc*2-Ac*i.F.F-Bc*i.F.S);
					ans+=ma[temp]*mc[getmid(temp,i.F)]*i.S;
				}
			}
		}
		else if(Bb==0){
			if(Bc==0)ans=ACsame(vb,va,vc);
			else if(Aa*Bc==Ac*Ba)ans=ACsame(va,vb,vc);
			else{
				for(pair<pair<int,int>,int> i:mb){
					temp=intersect(Aa,Ba,Ca,Ac,Bc,Cc*2-Ac*i.F.F-Bc*i.F.S);
					ans+=ma[temp]*mc[getmid(temp,i.F)]*i.S;
				}
			}
		}
		else if(Aa*Bb==Ab*Ba){
			if(Ab*Bc==Bb*Ac){
				if(Cc*Ac*2==Ca*Aa+Cb*Ab)ans=allsame(va,vb,vc);
				else ans=0;
			}
			else ans=ABsame(va,vb,vc);
		}
		else if(Bb*Ac==Bc*Ab)ans=ACsame(vb,va,vc);
		else if(Aa*Bc==Ac*Ba)ans=ACsame(va,vb,vc);
		else{
			for(pair<pair<int,int>,int> i:mb){
				temp=intersect(Aa,Ba,Ca,Ac,Bc,Cc*2-Ac*i.F.F-Bc*i.F.S);
				ans+=ma[temp]*mc[getmid(temp,i.F)]*i.S;
			}
		}
	}
	printf("%lld\n",ans);
}
accuracy: 0.1864406779661017
time_ms: 70
memory_kb: 20812
final_rank: 19

code_snippet: bool debug=false;
#include <algorithm>
#include <stdio.h>
#include <vector>
#include <utility>
#include <map>
#include <math.h>
using namespace std;
#define PB push_back
#define F first
#define S second
const int INF=1e9+10;
const int N=1e5+10;
const double pi=acos(-1);
pair<int,int> getmid(pair<int,int> a,pair<int,int> b){
	if(((a.F+b.F)&1)||((a.S+b.S)&1))return {INF,INF};
	return {(a.F+b.F)>>1,(a.S+b.S)>>1};
}
pair<int,int> getnxt(pair<int,int> a,pair<int,int> c){
	return {(c.F-a.F)*2+a.F,(c.S-a.S)*2+a.S};
}
__int128 myabs(__int128 x){return x>0?x:-x;}
pair<int,int> intersect(__int128 Aa,__int128 Ba,__int128 Ca,__int128 Ab,__int128 Bb,__int128 Cb){
	__int128 x=Ba*Cb-Bb*Ca,y=Ca*Ab-Cb*Aa,det=Ba*Ab-Aa*Bb;
	if(x%det!=0)return {INF,INF};
	if(y%det!=0)return {INF,INF};
	x/=det;
	y/=det;
	if(myabs(x)>N)return {INF,INF};
	if(myabs(y)>N)return {INF,INF};
	return {x,y};
}
pair<double,double> mul(pair<double,double> a,pair<double,double> b){
	return {a.F*b.F-a.S*b.S,a.F*b.S+a.S*b.F};
}
void fft(vector<pair<double,double>>& v,int size,bool on){
    pair<double,double> wn,u,t,w,inv;
	for(int i=1,j=size>>1,k;i<(size-1);i++){
        if(i<j)swap(v[i],v[j]);
        k=size>>1;
        while(j&k){
            j^=k;
            k>>=1;
        }
        j|=k;
    }
    for(int i=2;i<=size;i<<=1){
        wn={cos(2*pi/i),sin(2*pi/i)};
		if(on)wn.S=-wn.S;
        for(int j=0;j<size;j+=i){
            w={1,0};
            for(int k=j;k<j+(i>>1);k++){
                u=v[k];
                t=mul(w,v[k+(i>>1)]);
                v[k]={u.F+t.F,u.S+t.S};
                v[k+(i>>1)]={u.F-t.F,u.S-t.S};
                w=mul(wn,w);
            }
        }
    }
    if(on){
        inv={1.0/size,0};
        for(int i=0;i<size;i++)v[i]=mul(v[i],inv);
    }
    return ;
}
long long int allsame(vector<pair<int,int>>&va,vector<pair<int,int>>&vb,vector<pair<int,int>>&vc){
	vector<pair<double,double>> a,b;
	vector<long long int> c;
	long long int ans=0;
	int n=N<<2,sz=1;
	while(sz<n)sz<<=1;
	a.resize(sz,{0,0});
	b.resize(sz,{0,0});
	c.resize(sz>>1,0);
	if(va[0].F==va.back().F){
		for(pair<int,int> i:va)a[i.S+N].F+=1;
		for(pair<int,int> i:vb)b[i.S+N].F+=1;
		for(pair<int,int> i:vc)c[i.S+N]++;
	}
	else{
		for(pair<int,int> i:va)a[i.F+N].F+=1;
		for(pair<int,int> i:vb)b[i.F+N].F+=1;
		for(pair<int,int> i:vc)c[i.F+N]++;
	}
	if(debug){
		printf("a::\n");for(int i=0;i<sz;i++)if(a[i].F>0)printf("%d::(%.2lf,%.2lf)\n",i,a[i].F,a[i].S);
		printf("b::\n");for(int i=0;i<sz;i++)if(b[i].F>0)printf("%d::(%.2lf,%.2lf)\n",i,b[i].F,b[i].S);
	}
	fft(a,sz,0);
	fft(b,sz,0);
	for(int i=0;i<a.size();i++)a[i]=mul(a[i],b[i]);
	fft(a,sz,1);
	if(debug){
		printf("after::\n");for(int i=0;i<sz;i++)if(a[i].F>0)printf("%d::(%.2lf,%.2lf)\n",i,a[i].F,a[i].S);
		printf("c::\n");for(int i=0;i<(sz>>1);i++)if(c[i]>0)printf("%d::%d\n",i,c[i]);
	}
	for(int i=0;i<(sz>>1);i++)ans+=c[i]*((long long int)(a[i<<1].F+0.5));
	return ans;
}
long long int ABsame(vector<pair<int,int>>&va,vector<pair<int,int>>&vb,vector<pair<int,int>>&vc){
	vector<pair<double,double>> a,b;
	int n=N<<2,sz=1;
	pair<int,int> temp;
	long long int Aa,Ba,Ca,Cb,Ac,Bc,Cc;
	while(sz<n)sz<<=1;
	a.resize(sz,{0,0});
	b.resize(sz,{0,0});
	if(va[0].F==va.back().F){
		for(pair<int,int> i:va)a[i.S+N].F+=1;
		for(pair<int,int> i:vb)b[i.S+N].F+=1;
	}
	else{
		for(pair<int,int> i:va)a[i.F+N].F+=1;
		for(pair<int,int> i:vb)b[i.F+N].F+=1;
	}
	fft(a,sz,0);
	fft(b,sz,0);
	for(int i=0;i<a.size();i++)a[i]=mul(a[i],b[i]);
	fft(a,sz,1);
	Aa=va[0].S-va.back().S,Ba=va.back().F-va[0].F;
	Ca=Aa*va[0].F+Ba*va[0].S;
	Cb=Aa*vb[0].F+Ba*vb[0].S;
	Ac=vc[0].S-vc.back().S,Bc=vc.back().F-vc[0].F;
	Cc=Ac*vc[0].F+Bc*vc[0].S;
	temp=intersect(Aa*2,Ba*2,Ca+Cb,Ac,Bc,Cc);
	if(va[0].F==va.back().F)return ((long long int)(a[(temp.S+N)<<1].F+0.5))*(upper_bound(vc.begin(),vc.end(),temp)-lower_bound(vc.begin(),vc.end(),temp));
	else return ((long long int)(a[(temp.S+N)<<1].F+0.5))*(upper_bound(vc.begin(),vc.end(),temp)-lower_bound(vc.begin(),vc.end(),temp));
}
long long int ACsame(vector<pair<int,int>>&va,vector<pair<int,int>>&vb,vector<pair<int,int>>&vc){
	vector<pair<double,double>>a,b;
	vector<long long int> c;
	int n=N<<2,sz=1;
	long long int ans=0,Aa,Ba,Ca,Ab,Bb,Cb,Cc;
	pair<int,int> temp;
	while(sz<n)sz<<=1;
	a.resize(sz,{0,0});
	b.resize(sz,{0,0});
	c.resize(sz>>1,0);
	Aa=va[0].S-va.back().S,Ba=va.back().F-va[0].F;
	Ca=Aa*va[0].F+Ba*va[0].S;
	Cc=Aa*vc[0].F+Ba*vc[0].S;
	Ab=vb[0].S-vb.back().S,Bb=vb.back().F-vb[0].F;
	Cb=Ab*vb[0].F+Bb*vb[0].S;
	temp=intersect(Aa,Ba,Cc*2-Ca,Ab,Bb,Cb);
	if(va[0].F==va.back().F){
		for(pair<int,int> i:va)a[i.S+N].F+=1;
		for(pair<int,int> i:vc)c[i.S+N]++;
		b[temp.S+N].F=upper_bound(vb.begin(),vb.end(),temp)-lower_bound(vb.begin(),vb.end(),temp);
	}
	else{
		for(pair<int,int> i:va)a[i.F+N].F+=1;
		for(pair<int,int> i:vc)c[i.F+N]++;
		b[temp.F+N].F=upper_bound(vb.begin(),vb.end(),temp)-lower_bound(vb.begin(),vb.end(),temp);
	}
	fft(a,sz,0);
	fft(b,sz,0);
	for(int i=0;i<sz;i++)a[i]=mul(a[i],b[i]);
	fft(a,sz,1);
	for(int i=0;i<(sz>>1);i++)ans+=c[i]*((long long int)(a[i<<1].F+0.5));
	return ans;
}
int main(){
	int a,b,c;
	__int128 Aa,Ab,Ac,Ba,Bb,Bc,Ca,Cb,Cc;
	long long int ans=0;
	map<pair<int,int>,long long int> ma,mb,mc;
	map<pair<int,int>,long long int>::iterator u,t;
	pair<int,int> temp;
	vector<pair<int,int>> va,vb,vc;
	scanf("%d%d%d",&a,&b,&c);
	for(int i=1;i<=a;i++){
		scanf("%d%d",&temp.F,&temp.S);
		va.PB(temp);
		ma[temp]++;
	}
	for(int i=1;i<=b;i++){
		scanf("%d%d",&temp.F,&temp.S);
		vb.PB(temp);
		mb[temp]++;
	}
	for(int i=1;i<=c;i++){
		scanf("%d%d",&temp.F,&temp.S);
		vc.PB(temp);
		mc[temp]++;
	}
	if(ma.size()==1)for(int i=1;i<=b;i++)ans+=mc[getmid(va[0],vb[i])]*a;
	else if(mb.size()==1)for(int i=1;i<=a;i++)ans+=mc[getmid(va[i],vb[0])]*b;
	else if(mc.size()==1)for(int i=1;i<=a;i++)ans+=mb[getnxt(va[i],vc[0])]*c;
	else{
		u=ma.begin(),t=ma.end();
		t--;
		Aa=u->F.S-t->F.S,Ba=t->F.F-u->F.F;
		Ca=Aa*(u->F.F)+Ba*(u->F.S);
		u=mb.begin(),t=mb.end();
		t--;
		Ab=u->F.S-t->F.S,Bb=t->F.F-u->F.F;
		Cb=Ab*(u->F.F)+Bb*(u->F.S);
		u=mc.begin(),t=mc.end();
		t--;
		Ac=u->F.S-t->F.S,Bc=t->F.F-u->F.F;
		Cc=Ac*(u->F.F)+Bc*(u->F.S);
		if(Aa*Bb==Ab*Ba){
			if(Ab*Bc==Bb*Ac){
			    if(Ca+Cb==Cc*2)ans=allsame(va,vb,vc);
			    else ans=0;
			}
			else ans=ABsame(va,vb,vc);
		}
		else if(Bb*Ac==Bc*Ab)ans=ACsame(vb,va,vc);
		else if(Aa*Bc==Ac*Ba)ans=ACsame(va,vb,vc);
		else{
			for(pair<pair<int,int>,long long int> i:mb){
				temp=intersect(Aa,Ba,Ca,Ac,Bc,Cc*2-Ac*i.F.F-Bc*i.F.S);
				ans+=ma[temp]*mc[getmid(temp,i.F)]*i.S;
			}
		}
	}
	printf("%lld\n",ans);
}
accuracy: 0.3220338983050847
time_ms: 120
memory_kb: 20892
final_rank: 16

code_snippet: bool debug=false;
#include <algorithm>
#include <stdio.h>
#include <vector>
#include <utility>
#include <map>
#include <math.h>
using namespace std;
#define PB push_back
#define F first
#define S second
const int INF=1e9+10;
const int N=1e5+10;
const double pi=acos(-1);
pair<int,int> getmid(pair<int,int> a,pair<int,int> b){
	if(((a.F+b.F)&1)||((a.S+b.S)&1))return {INF,INF};
	return {(a.F+b.F)>>1,(a.S+b.S)>>1};
}
pair<int,int> getnxt(pair<int,int> a,pair<int,int> c){
	return {(c.F-a.F)*2+a.F,(c.S-a.S)*2+a.S};
}
__int128 myabs(__int128 x){return x>0?x:-x;}
pair<int,int> intersect(__int128 Aa,__int128 Ba,__int128 Ca,__int128 Ab,__int128 Bb,__int128 Cb){
	__int128 x=Ba*Cb-Bb*Ca,y=Ca*Ab-Cb*Aa,det=Ba*Ab-Aa*Bb;
	if(x%det!=0)return {INF,INF};
	if(y%det!=0)return {INF,INF};
	x/=det;
	y/=det;
	if(myabs(x)>N)return {INF,INF};
	if(myabs(y)>N)return {INF,INF};
	return {x,y};
}
pair<double,double> mul(pair<double,double> a,pair<double,double> b){
	return {a.F*b.F-a.S*b.S,a.F*b.S+a.S*b.F};
}
void fft(vector<pair<double,double>>& v,int size,bool on){
    pair<double,double> wn,u,t,w,inv;
	for(int i=1,j=size>>1,k;i<(size-1);i++){
        if(i<j)swap(v[i],v[j]);
        k=size>>1;
        while(j&k){
            j^=k;
            k>>=1;
        }
        j|=k;
    }
    for(int i=2;i<=size;i<<=1){
        wn={cos(2*pi/i),sin(2*pi/i)};
		if(on)wn.S=-wn.S;
        for(int j=0;j<size;j+=i){
            w={1,0};
            for(int k=j;k<j+(i>>1);k++){
                u=v[k];
                t=mul(w,v[k+(i>>1)]);
                v[k]={u.F+t.F,u.S+t.S};
                v[k+(i>>1)]={u.F-t.F,u.S-t.S};
                w=mul(wn,w);
            }
        }
    }
    if(on){
        inv={1.0/size,0};
        for(int i=0;i<size;i++)v[i]=mul(v[i],inv);
    }
    return ;
}
long long int allsame(vector<pair<int,int>>&va,vector<pair<int,int>>&vb,vector<pair<int,int>>&vc){
	vector<pair<double,double>> a,b;
	vector<long long int> c;
	long long int ans=0;
	int n=N<<2,sz=1;
	while(sz<n)sz<<=1;
	a.resize(sz,{0,0});
	b.resize(sz,{0,0});
	c.resize(sz>>1,0);
	if(va[0].F==va.back().F){
		for(pair<int,int> i:va)a[i.S+N].F+=1;
		for(pair<int,int> i:vb)b[i.S+N].F+=1;
		for(pair<int,int> i:vc)c[i.S+N]++;
	}
	else{
		for(pair<int,int> i:va)a[i.F+N].F+=1;
		for(pair<int,int> i:vb)b[i.F+N].F+=1;
		for(pair<int,int> i:vc)c[i.F+N]++;
	}
	if(debug){
		printf("a::\n");for(int i=0;i<sz;i++)if(a[i].F>0)printf("%d::(%.2lf,%.2lf)\n",i,a[i].F,a[i].S);
		printf("b::\n");for(int i=0;i<sz;i++)if(b[i].F>0)printf("%d::(%.2lf,%.2lf)\n",i,b[i].F,b[i].S);
	}
	fft(a,sz,0);
	fft(b,sz,0);
	for(int i=0;i<a.size();i++)a[i]=mul(a[i],b[i]);
	fft(a,sz,1);
	if(debug){
		printf("after::\n");for(int i=0;i<sz;i++)if(a[i].F>0)printf("%d::(%.2lf,%.2lf)\n",i,a[i].F,a[i].S);
		printf("c::\n");for(int i=0;i<(sz>>1);i++)if(c[i]>0)printf("%d::%d\n",i,c[i]);
	}
	for(int i=0;i<(sz>>1);i++)ans+=c[i]*((long long int)(a[i<<1].F+0.5));
	return ans;
}
long long int ABsame(vector<pair<int,int>>&va,vector<pair<int,int>>&vb,vector<pair<int,int>>&vc){
	vector<pair<double,double>> a,b;
	int n=N<<2,sz=1;
	pair<int,int> temp;
	long long int Aa,Ba,Ca,Cb,Ac,Bc,Cc;
	while(sz<n)sz<<=1;
	a.resize(sz,{0,0});
	b.resize(sz,{0,0});
	if(va[0].F==va.back().F){
		for(pair<int,int> i:va)a[i.S+N].F+=1;
		for(pair<int,int> i:vb)b[i.S+N].F+=1;
	}
	else{
		for(pair<int,int> i:va)a[i.F+N].F+=1;
		for(pair<int,int> i:vb)b[i.F+N].F+=1;
	}
	fft(a,sz,0);
	fft(b,sz,0);
	for(int i=0;i<a.size();i++)a[i]=mul(a[i],b[i]);
	fft(a,sz,1);
	Aa=va[0].S-va.back().S,Ba=va.back().F-va[0].F;
	Ca=Aa*va[0].F+Ba*va[0].S;
	Cb=Aa*vb[0].F+Ba*vb[0].S;
	Ac=vc[0].S-vc.back().S,Bc=vc.back().F-vc[0].F;
	Cc=Ac*vc[0].F+Bc*vc[0].S;
	temp=intersect(Aa*2,Ba*2,Ca+Cb,Ac,Bc,Cc);
	if(va[0].F==va.back().F)return ((long long int)(a[(temp.S+N)<<1].F+0.5))*(upper_bound(vc.begin(),vc.end(),temp)-lower_bound(vc.begin(),vc.end(),temp));
	else return ((long long int)(a[(temp.S+N)<<1].F+0.5))*(upper_bound(vc.begin(),vc.end(),temp)-lower_bound(vc.begin(),vc.end(),temp));
}
long long int ACsame(vector<pair<int,int>>&va,vector<pair<int,int>>&vb,vector<pair<int,int>>&vc){
	vector<pair<double,double>>a,b;
	vector<long long int> c;
	int n=N<<2,sz=1;
	long long int ans=0,Aa,Ba,Ca,Ab,Bb,Cb,Cc;
	pair<int,int> temp;
	while(sz<n)sz<<=1;
	a.resize(sz,{0,0});
	b.resize(sz,{0,0});
	c.resize(sz>>1,0);
	Aa=va[0].S-va.back().S,Ba=va.back().F-va[0].F;
	Ca=Aa*va[0].F+Ba*va[0].S;
	Cc=Aa*vc[0].F+Ba*vc[0].S;
	Ab=vb[0].S-vb.back().S,Bb=vb.back().F-vb[0].F;
	Cb=Ab*vb[0].F+Bb*vb[0].S;
	temp=intersect(Aa,Ba,Cc*2-Ca,Ab,Bb,Cb);
	if(va[0].F==va.back().F){
		for(pair<int,int> i:va)a[i.S+N].F+=1;
		for(pair<int,int> i:vc)c[i.S+N]++;
		b[temp.S+N].F=upper_bound(vb.begin(),vb.end(),temp)-lower_bound(vb.begin(),vb.end(),temp);
	}
	else{
		for(pair<int,int> i:va)a[i.F+N].F+=1;
		for(pair<int,int> i:vc)c[i.F+N]++;
		b[temp.F+N].F=upper_bound(vb.begin(),vb.end(),temp)-lower_bound(vb.begin(),vb.end(),temp);
	}
	fft(a,sz,0);
	fft(b,sz,0);
	for(int i=0;i<sz;i++)a[i]=mul(a[i],b[i]);
	fft(a,sz,1);
	for(int i=0;i<(sz>>1);i++)ans+=c[i]*((long long int)(a[i<<1].F+0.5));
	return ans;
}
int main(){
	int a,b,c;
	__int128 Aa,Ab,Ac,Ba,Bb,Bc,Ca,Cb,Cc;
	long long int ans=0;
	map<pair<int,int>,long long int> ma,mb,mc;
	map<pair<int,int>,long long int>::iterator u,t;
	pair<int,int> temp;
	vector<pair<int,int>> va,vb,vc;
	scanf("%d%d%d",&a,&b,&c);
	for(int i=1;i<=a;i++){
		scanf("%d%d",&temp.F,&temp.S);
		va.PB(temp);
		ma[temp]++;
	}
	for(int i=1;i<=b;i++){
		scanf("%d%d",&temp.F,&temp.S);
		vb.PB(temp);
		mb[temp]++;
	}
	for(int i=1;i<=c;i++){
		scanf("%d%d",&temp.F,&temp.S);
		vc.PB(temp);
		mc[temp]++;
	}
	if(ma.size()==1)for(int i=1;i<=b;i++)ans+=mc[getmid(va[0],vb[i])]*a;
	else if(mb.size()==1)for(int i=1;i<=a;i++)ans+=mc[getmid(va[i],vb[0])]*b;
	else if(mc.size()==1)for(int i=1;i<=a;i++)ans+=mb[getnxt(va[i],vc[0])]*c;
	else{
		u=ma.begin(),t=ma.end();
		t--;
		Aa=u->F.S-t->F.S,Ba=t->F.F-u->F.F;
		Ca=Aa*(u->F.F)+Ba*(u->F.S);
		u=mb.begin(),t=mb.end();
		t--;
		Ab=u->F.S-t->F.S,Bb=t->F.F-u->F.F;
		Cb=Ab*(u->F.F)+Bb*(u->F.S);
		u=mc.begin(),t=mc.end();
		t--;
		Ac=u->F.S-t->F.S,Bc=t->F.F-u->F.F;
		Cc=Ac*(u->F.F)+Bc*(u->F.S);
		if(Aa*Bb==Ab*Ba){
			if(Ab*Bc==Bb*Ac)ans=allsame(va,vb,vc);
			else ans=ABsame(va,vb,vc);
		}
		else if(Bb*Ac==Bc*Ab)ans=ACsame(vb,va,vc);
		else if(Aa*Bc==Ac*Ba)ans=ACsame(va,vb,vc);
		else{
			for(pair<pair<int,int>,long long int> i:mb){
				temp=intersect(Aa,Ba,Ca,Ac,Bc,Cc*2-Ac*i.F.F-Bc*i.F.S);
				ans+=ma[temp]*mc[getmid(temp,i.F)]*i.S;
			}
		}
	}
	printf("%lld\n",ans);
}
accuracy: 0.5932203389830508
time_ms: 190
memory_kb: 37904
final_rank: 11

code_snippet: bool debug=false;
#include <algorithm>
#include <stdio.h>
#include <vector>
#include <utility>
#include <map>
#include <math.h>
using namespace std;
#define PB push_back
#define F first
#define S second
const int INF=1e9+10;
const int N=1e5+10;
const double pi=acos(-1);
pair<int,int> getmid(pair<int,int> a,pair<int,int> b){
	if(((a.F+b.F)&1)||((a.S+b.S)&1))return {INF,INF};
	return {(a.F+b.F)>>1,(a.S+b.S)>>1};
}
pair<int,int> getnxt(pair<int,int> a,pair<int,int> c){
	return {(c.F-a.F)*2+a.F,(c.S-a.S)*2+a.S};
}
__int128 myabs(__int128 x){return x>0?x:-x;}
pair<int,int> intersect(__int128 Aa,__int128 Ba,__int128 Ca,__int128 Ab,__int128 Bb,__int128 Cb){
	__int128 x=Ba*Cb-Bb*Ca,y=Ca*Ab-Cb*Aa,det=Ba*Ab-Aa*Bb;
	if(x%det!=0)return {INF,INF};
	if(y%det!=0)return {INF,INF};
	x/=det;
	y/=det;
	if(myabs(x)>N)return {INF,INF};
	if(myabs(y)>N)return {INF,INF};
	return {x,y};
}
pair<double,double> mul(pair<double,double> a,pair<double,double> b){
	return {a.F*b.F-a.S*b.S,a.F*b.S+a.S*b.F};
}
void fft(vector<pair<double,double>>& v,int size,bool on){
    pair<double,double> wn,u,t,w,inv;
	for(int i=1,j=size>>1,k;i<(size-1);i++){
        if(i<j)swap(v[i],v[j]);
        k=size>>1;
        while(j&k){
            j^=k;
            k>>=1;
        }
        j|=k;
    }
    for(int i=2;i<=size;i<<=1){
        wn={cos(2*pi/i),sin(2*pi/i)};
		if(on)wn.S=-wn.S;
        for(int j=0;j<size;j+=i){
            w={1,0};
            for(int k=j;k<j+(i>>1);k++){
                u=v[k];
                t=mul(w,v[k+(i>>1)]);
                v[k]={u.F+t.F,u.S+t.S};
                v[k+(i>>1)]={u.F-t.F,u.S-t.S};
                w=mul(wn,w);
            }
        }
    }
    if(on){
        inv={1.0/size,0};
        for(int i=0;i<size;i++)v[i]=mul(v[i],inv);
    }
    return ;
}
long long int allsame(vector<pair<int,int>>&va,vector<pair<int,int>>&vb,vector<pair<int,int>>&vc){
	vector<pair<double,double>> a,b;
	vector<long long int> c;
	long long int ans=0;
	int n=N<<2,sz=1;
	while(sz<n)sz<<=1;
	a.resize(sz,{0,0});
	b.resize(sz,{0,0});
	c.resize(sz>>1,0);
	if(va[0].F==va.back().F){
		for(pair<int,int> i:va)a[i.S+N].F+=1;
		for(pair<int,int> i:vb)b[i.S+N].F+=1;
		for(pair<int,int> i:vc)c[i.S+N]++;
	}
	else{
		for(pair<int,int> i:va)a[i.F+N].F+=1;
		for(pair<int,int> i:vb)b[i.F+N].F+=1;
		for(pair<int,int> i:vc)c[i.F+N]++;
	}
	if(debug){
		printf("a::\n");for(int i=0;i<sz;i++)if(a[i].F>0)printf("%d::(%.2lf,%.2lf)\n",i,a[i].F,a[i].S);
		printf("b::\n");for(int i=0;i<sz;i++)if(b[i].F>0)printf("%d::(%.2lf,%.2lf)\n",i,b[i].F,b[i].S);
	}
	fft(a,sz,0);
	fft(b,sz,0);
	for(int i=0;i<a.size();i++)a[i]=mul(a[i],b[i]);
	fft(a,sz,1);
	if(debug){
		printf("after::\n");for(int i=0;i<sz;i++)if(a[i].F>0)printf("%d::(%.2lf,%.2lf)\n",i,a[i].F,a[i].S);
		printf("c::\n");for(int i=0;i<(sz>>1);i++)if(c[i]>0)printf("%d::%d\n",i,c[i]);
	}
	for(int i=0;i<(sz>>1);i++)ans+=c[i]*((long long int)(a[i<<1].F+0.5));
	return ans;
}
long long int ABsame(vector<pair<int,int>>&va,vector<pair<int,int>>&vb,vector<pair<int,int>>&vc){
	vector<pair<double,double>> a,b;
	int n=N<<2,sz=1;
	pair<int,int> temp;
	long long int Aa,Ba,Ca,Cb,Ac,Bc,Cc;
	while(sz<n)sz<<=1;
	a.resize(sz,{0,0});
	b.resize(sz,{0,0});
	if(va[0].F==va.back().F){
		for(pair<int,int> i:va)a[i.S+N].F+=1;
		for(pair<int,int> i:vb)b[i.S+N].F+=1;
	}
	else{
		for(pair<int,int> i:va)a[i.F+N].F+=1;
		for(pair<int,int> i:vb)b[i.F+N].F+=1;
	}
	fft(a,sz,0);
	fft(b,sz,0);
	for(int i=0;i<a.size();i++)a[i]=mul(a[i],b[i]);
	fft(a,sz,1);
	Aa=va[0].S-va.back().S,Ba=va.back().F-va[0].F;
	Ca=Aa*va[0].F+Ba*va[0].S;
	Cb=Aa*vb[0].F+Ba*vb[0].S;
	Ac=vc[0].S-vc.back().S,Bc=vc.back().F-vc[0].F;
	Cc=Ac*vc[0].F+Bc*vc[0].S;
	temp=intersect(Aa*2,Ba*2,Ca+Cb,Ac,Bc,Cc);
	if(va[0].F==va.back().F)return ((long long int)(a[(temp.S+N)<<1].F+0.5))*(upper_bound(vc.begin(),vc.end(),temp)-lower_bound(vc.begin(),vc.end(),temp));
	else return ((long long int)(a[(temp.S+N)<<1].F+0.5))*(upper_bound(vc.begin(),vc.end(),temp)-lower_bound(vc.begin(),vc.end(),temp));
}
long long int ACsame(vector<pair<int,int>>&va,vector<pair<int,int>>&vb,vector<pair<int,int>>&vc){
	vector<pair<double,double>>a,b;
	vector<long long int> c;
	int n=N<<2,sz=1;
	long long int ans=0,Aa,Ba,Ca,Ab,Bb,Cb,Cc;
	pair<int,int> temp;
	while(sz<n)sz<<=1;
	a.resize(sz,{0,0});
	b.resize(sz,{0,0});
	c.resize(sz>>1,0);
	Aa=va[0].S-va.back().S,Ba=va.back().F-va[0].F;
	Ca=Aa*va[0].F+Ba*va[0].S;
	Cc=Aa*vc[0].F+Ba*vc[0].S;
	Ab=vb[0].S-vb.back().S,Bb=vb.back().F-vb[0].F;
	Cb=Ab*vb[0].F+Bb*vb[0].S;
	temp=intersect(Aa,Ba,Cc*2-Ca,Ab,Bb,Cb);
	if(va[0].F==va.back().F){
		for(pair<int,int> i:va)a[i.S+N].F+=1;
		for(pair<int,int> i:vc)c[i.S+N]++;
		b[temp.S+N].F=upper_bound(vb.begin(),vb.end(),temp)-lower_bound(vb.begin(),vb.end(),temp);
	}
	else{
		for(pair<int,int> i:va)a[i.F+N].F+=1;
		for(pair<int,int> i:vc)c[i.F+N]++;
		b[temp.F+N].F=upper_bound(vb.begin(),vb.end(),temp)-lower_bound(vb.begin(),vb.end(),temp);
	}
	fft(a,sz,0);
	fft(b,sz,0);
	for(int i=0;i<sz;i++)a[i]=mul(a[i],b[i]);
	fft(a,sz,1);
	for(int i=0;i<(sz>>1);i++)ans+=c[i]*((long long int)(a[i<<1].F+0.5));
	return ans;
}
int main(){
	int a,b,c;
	__int128 Aa,Ab,Ac,Ba,Bb,Bc,Ca,Cb,Cc;
	long long int ans=0;
	map<pair<int,int>,int> ma,mb,mc;
	map<pair<int,int>,int>::iterator u,t;
	pair<int,int> temp;
	vector<pair<int,int>> va,vb,vc;
	scanf("%d%d%d",&a,&b,&c);
	for(int i=1;i<=a;i++){
		scanf("%d%d",&temp.F,&temp.S);
		va.PB(temp);
		ma[temp]++;
	}
	for(int i=1;i<=b;i++){
		scanf("%d%d",&temp.F,&temp.S);
		vb.PB(temp);
		mb[temp]++;
	}
	for(int i=1;i<=c;i++){
		scanf("%d%d",&temp.F,&temp.S);
		vc.PB(temp);
		mc[temp]++;
	}
	if(ma.size()==1)for(int i=1;i<=b;i++)ans+=mc[getmid(va[0],vb[i])]*a;
	else if(mb.size()==1)for(int i=1;i<=a;i++)ans+=mc[getmid(va[i],vb[0])]*b;
	else if(mc.size()==1)for(int i=1;i<=a;i++)ans+=mb[getnxt(va[i],vc[0])]*c;
	else{
		u=ma.begin(),t=ma.end();
		t--;
		Aa=u->F.S-t->F.S,Ba=t->F.F-u->F.F;
		Ca=Aa*(u->F.F)+Ba*(u->F.S);
		u=mb.begin(),t=mb.end();
		t--;
		Ab=u->F.S-t->F.S,Bb=t->F.F-u->F.F;
		Cb=Ab*(u->F.F)+Bb*(u->F.S);
		u=mc.begin(),t=mc.end();
		t--;
		Ac=u->F.S-t->F.S,Bc=t->F.F-u->F.F;
		Cc=Ac*(u->F.F)+Bc*(u->F.S);
		if(Aa*Bb==Ab*Ba){
			if(Ab*Bc==Bb*Ac)ans=allsame(va,vb,vc);
			else ans=ABsame(va,vb,vc);
		}
		else if(Bb*Ac==Bc*Ab)ans=ACsame(vb,va,vc);
		else if(Aa*Bc==Ac*Ba)ans=ACsame(va,vb,vc);
		else{
			for(pair<pair<int,int>,int> i:mb){
				temp=intersect(Aa,Ba,Ca,Ac,Bc,Cc*2-Ac*i.F.F-Bc*i.F.S);
				ans+=ma[temp]*mc[getmid(temp,i.F)]*i.S;
			}
		}
	}
	printf("%lld\n",ans);
}
accuracy: 0.1864406779661017
time_ms: 70
memory_kb: 20888
final_rank: 20