在已有的点集中按X坐标从小到大排序,每增加一个点,找到大于等于它的位置p,分为两部分,然后从右递增计算要增加的点与点集中的点的距离,若>=Min,则退出,然后再从p-1处从右往左递减计算要增加的点与点集中所有点的距离的最小值。
#include <cstdio>
#include <set>
#include <algorithm>
using namespace std;
#define LL long long
#define N 500005
struct node
{
LL x,y;
bool operator <(const node &p) const
{
return x<p.x;
}
};
multiset <node> mset;
const LL INF=((LL)1<<62);
int n,m;
LL MIN;
LL solve(LL x,LL y,int cur)
{
node v;
v.x=x;
v.y=y;
if(!cur)
{
mset.insert(v);
return 0;
}
multiset<node>::iterator p=mset.lower_bound(v),q;
for(q=p; q!=mset.begin(); )
{
q--;
LL a=(q->x)-x;
a=a*a;
if(a>=MIN) break;
LL b=(q->y)-y;
b=b*b;
MIN=min(a+b,MIN);
}
for(; p!=mset.end(); ++p)
{
LL a=(p->x)-x;
a=a*a;
if(a>=MIN) break;
LL b=(p->y)-y;
b=b*b;
MIN=min(a+b,MIN);
}
mset.insert(v);
return MIN;
}
int main()
{
// freopen("in.txt","r",stdin);
int t;
scanf("%d",&t);
while(t--)
{
mset.clear();
LL x=0,y=0,A1,A2,A3,B1,B2,B3;
LL sum=0;
scanf("%d%I64d%I64d%I64d%I64d%I64d%I64d",&n,&A1,&A2,&A3,&B1,&B2,&B3);
MIN=INF;
for(int i=0; i<n; ++i)
{
x=(x*A1+A2)%A3;
y=(y*B1+B2)%B3;
sum+=solve(x,y,i);
}
printf("%I64d\n",sum);
}
return 0;
}