1 /*将x从小到大排序,每次插入一个点,直接找比这个点的x大的第一个,然后从这个开始向两边找 2 ,找点的下标用多重容器实现*/ 3 #include<stdio.h> 4 #include<string.h> 5 #include<algorithm> 6 #include<set> 7 #include<algorithm> 8 #include<iostream> 9 using namespace std; 10 struct point 11 { 12 __int64 x,y; 13 bool operator<(const point &a) const 14 { 15 return x<a.x; 16 } 17 }; 18 void cacl(__int64 n,__int64 x[]) 19 { 20 __int64 a,b,c; 21 scanf("%I64d%I64d%I64d",&a,&b,&c); 22 int i; 23 x[0]=0; 24 for(i=1;i<=n;i++) 25 x[i]=(x[i-1]*a+b)%c; 26 } 27 __int64 min(__int64 a,__int64 b) 28 { 29 if(a<b) return a; 30 return b; 31 } 32 __int64 x[500005],y[500005],n; 33 void find() 34 { 35 __int64 i,j; 36 __int64 ans,sum; 37 __int64 m1,m2; 38 scanf("%I64d",&n); 39 cacl(n,x); 40 cacl(n,y); 41 //for(i=1;i<=n;i++) 42 // printf("%I64d %I64d ",x[i],y[i]); 43 ans=(__int64)1<<60; 44 sum=0; 45 multiset<point> M; 46 for(i=1;i<=n;i++) 47 { 48 point p; 49 p.x=x[i]; p.y=y[i]; 50 51 if(i>1)//从第二个点开始 52 { 53 multiset<point>::iterator it=M.lower_bound(p),e; 54 for(e=it;e!=M.end();e++) 55 { 56 m1=e->x-p.x;////差值 57 if(m1*m1>=ans) break; 58 m2=e->y-p.y; 59 ans=min(ans,m1*m1+m2*m2); 60 } 61 for(e=it;e!=M.begin();) 62 { 63 e--;//防止重复,上面已经找过it了 64 m1=e->x-p.x; 65 if(m1*m1>=ans) break; 66 m2=e->y-p.y; 67 ans=ans=min(ans,m1*m1+m2*m2); 68 } 69 sum=sum+ans; 70 } 71 M.insert(p); 72 } 73 printf("%I64d ",sum); 74 } 75 int main() 76 { 77 int t; 78 scanf("%d",&t); 79 while(t--) 80 { 81 find(); 82 } 83 return 0; 84 }