题意:给出A、B、C,按照给出的公式推出每一个点,添加每一个点时,求出相应的最短距离,所有最短距离加和
因为是随机点,不可能有边界数据,所以可以爆搞
每次找(0,R-1)区间的最近点对(R为上一个最近点对里面编号最大的),然后加上R到N里面所有的距离(相乘即可)
这题搞出来的。。。应该不是什么正规解法。。。跑了19015ms。。。还是太水了
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
#define LL long long
const int maxn = 500050;
typedef struct Point
{
int Id;
int No;
LL x,y;
Point(LL _x=0,LL _y=0,int _Id=0):x(_x),y(_y),Id(_Id){}
bool operator < (const Point &a) const{
return x<a.x || (x==a.x && y<a.y);
}
}Point;
typedef struct Pair
{
LL dis;
int na;
int nb;
bool operator < (const Pair &a) const{
return dis<a.dis ;
}
} Pair;
int n;
Point P[maxn];
Point p[maxn],py[maxn];
int cmpy(Point a, Point b)
{
return a.y < b.y;
}
Pair dis(Point a, Point b)
{
Pair p;
p.dis=(a.x - b.x)*(a.x - b.x) + (a.y - b.y)*(a.y - b.y);
p.na=a.No;
p.nb=b.No;
return p;
}
Pair closest( int l, int r )
{
if( l+1 == r )
return dis( p[l], p[r]) ;
if( l+2 == r )
return min( dis(p[l],p[l+1]), min( dis(p[l+1],p[r]), dis(p[l],p[r]) ) ) ;
int mid = (l+r)/2 ;
Pair pr = min( closest(l,mid), closest(mid+1,r) ) ;
int i, j, cnt=0 ;
for( i=l; i<=r; i++ ){
if( p[i].x >= p[mid].x-pr.dis && p[i].x <= p[mid].x+pr.dis ){
py[cnt++] = p[i] ;
}
}
sort( py, py+cnt, cmpy ) ;
for( i=0; i<cnt; i++ ){
for( j=i+1; j<cnt && (py[j].y-py[i].y)*(py[j].y-py[i].y)<pr.dis; j++ ){
// py数组中的点是按照y坐标升序的
pr = min( pr, dis(py[i],py[j]) ) ;
}
}
return pr ;
}
int main()
{
int T,n;
LL ax,ay,bx,by,cx,cy;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
scanf("%I64d%I64d%I64d%I64d%I64d%I64d",&ax,&bx,&cx,&ay,&by,&cy);
P[0]=Point(0,0,0);
for(int i=1;i<=n;i++)
{
LL x = (P[i-1].x*ax + bx)%cx;
LL y = (P[i-1].y*ay + by)%cy;
P[i] = Point(x,y,i);
}
int end=n;
LL ans=0;
while(end>1)
{
for(int i = 0;i < end;i++)
p[i] = P[i+1];
sort(p, p+end);
for(int i = 0;i < end;i++)
p[i].No = i;
Pair pr = closest(0,end-1);
int Max = max(p[pr.na].Id,p[pr.nb].Id);
ans += (end-Max+1)*dis(p[pr.na],p[pr.nb]).dis;
end = Max-1;
}
printf("%I64d\n",ans);
}
return 0;
}