简要题意:
无限大的棋盘上放了 n n n个棋子,你还可以再放不超过 k k k 个棋子,使得最终棋子的位置中心对称。请问可能的不同的对称中心有多少个?
n ≤ 1 e 5 , k ≤ 20 n\leq 1e5,k\leq 20 n≤1e5,k≤20
题解:
考虑中心对称也就是说它们配对之后横纵坐标之和相等。
按照 x x x 为第一关键字 y y y 为第二关键字排序。在确定对称中心之后可以双指针求出匹配对数,剩下独立点不超过 k k k 个即可用棋子来一一匹配。
考虑最左 k + 1 k+1 k+1个和最右 k + 1 k+1 k+1个,必然有左边一个或右边一个没有被你放的棋子匹配,由此可以确定对称中心。
代码:
#include<bits/stdc++.h>
#define ll long long
#define re register
#define cs const
namespace IO{
inline char gc(){
static cs int Rlen=1<<22|1;static char buf[Rlen],*p1,*p2;
return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,Rlen,stdin),p1==p2)?EOF:*p1++;
}template<typename T>T get_integer(){
char c;bool f=false;while(!isdigit(c=gc()))f=c=='-';T x=c^48;
while(isdigit(c=gc()))x=((x+(x<<2))<<1)+(c^48);return f?-x:x;
}inline int gi(){return get_integer<int>();}
}using namespace IO;
using std::cerr;
using std::cout;
#define fi first
#define se second
cs int N=1e5+7;
int n,k;
struct pt{int x,y;pt(){}pt(int _x,int _y):x(_x),y(_y){}}p[N];
inline bool operator<(cs pt &a,cs pt &b){
return a.x<b.x||(a.x==b.x&&a.y<b.y);
}
inline bool operator==(cs pt &a,cs pt &b){return a.x==b.x&&a.y==b.y;}
inline pt operator+(cs pt &a,cs pt &b){return pt(a.x+b.x,a.y+b.y);}
inline pt operator-(cs pt &a,cs pt &b){return pt(a.x-b.x,a.y-b.y);}
std::set<pt> S;int ans;
void calc(cs pt &O){
if(S.find(O)!=S.end())return;
S.insert(O);int need=0;
for(int re l=1,r=n;l<=r;)
if(p[l]+p[r]==O)++l,--r;
else {
++need;
(p[l]+p[r]<O)?++l:--r;
}
if(need<=k)++ans;
}
void Main(){
n=gi(),k=gi();
if(k>=n){
puts("-1");return ;
}
for(int re i=1;i<=n;++i)
p[i].x=gi(),p[i].y=gi();
for(int re i=1;i<=k+1;++i)
for(int re j=n-k;j<=n;++j)
calc(p[i]+p[j]);
cout<<ans<<"\n";
}
inline void file(){
#ifdef zxyoi
freopen("chess.in","r",stdin);
#else
#ifndef ONLINE_JUDGE
freopen("chess.in","r",stdin);
freopen("chess.out","w",stdout);
#endif
#endif
}
signed main(){file();Main();return 0;}