链接:https://darkbzoj.tk/problem/1100
题意:找多边形的对称轴个数。
思路:hash之后找一个环形回文串。等价于一个序列可以由两个回文串拼接而成。
#include <iostream>
#include <cassert>
#include <limits>
using namespace std;
#define DEBUG 0
#define MAXN 200011
typedef long long LL;
typedef LL LT;
template <typename T>
T Add(T x, int p) {
return x >= p ? x - p : x;
}
template <typename T>
T Sub(T x, int p) {
return x < 0 ? x + p : x;
}
template <typename T>
T sq(T x) {
return x * x;
}
int sgn(LT x) {
return x < 0 ? -1 : (x > 0 ? 1 : 0);
}
struct VEC {
LT x, y;
VEC operator + (const VEC& b) const {
return VEC{x + b.x, y + b.y};
}
bool operator == (const VEC& b) const {
return x == b.x && y == b.y;
}
bool operator < (const VEC& b) const {
return y != b.y ? y < b.y : x < b.x;
}
VEC operator - (const VEC& b) const {
return VEC{x - b.x, y - b.y};
}
LT len2() const {
return sq(x) + sq(y);
}
LT dist2(const VEC& b) const {
return (*this - b).len2();
}
//Might overflow
LT operator * (const VEC& b) const {
return x * b.x + y * b.y;
}
LT operator ^ (const VEC& b) const {
return x * b.y - y * b.x;
}
bool ToLeftTest(const VEC& b) const {
return (*this ^ b) > 0;
}
bool ToRightTest(const VEC& b) const {
return (*this ^ b) < 0;
}
void input() {
cin >> x >> y;
}
};
template <typename T>
void manacher( const T* str,int* r,int len,int n ){
int mx(0),c(1),i,j;
r[0] = r[len-1] = 1;
for( i = 1;i < len-1;i++ ){
if( mx >= i ) j = min( r[ (c<<1)-i ],mx-i+1 );
else j = 1;
while((i-j) >= 0 && i+j < len && str[i-j] == str[i+j] )++j;
if( i+j-1 > mx ){
mx = i+j-1;
c = i;
}
r[i] = j;
}
}
template <typename T>
int NumOfPalindromeSplit(const T s[], int n) {
const static T minf = numeric_limits<T>::min();
static int r[MAXN*2+7];
static T str[MAXN*2+7];
static int le[MAXN*2+7];
static int ri[MAXN*2+7];
for( int i = 0;i < n;i++ ){
str[i<<1] = minf;
str[i<<1|1] = s[i];
}
str[n<<1] = minf;
int len = n<<1|1;
manacher( str,r,len,n );
int p = -1;
for( int i = 0;i < len;i++ ){
while( p+1<i+r[i] ) {
++p;
le[p] = (p-i+1)*2-1;
}
}
p =len;
for( int i = len-1;i >= 0;i-- ){
while( p-1 > i-r[i] ){
--p;
ri[p] = (i-p+1)*2-1;
}
}
for( int i = 0;i < n;i++ ){
le[i] = (le[i<<1|1]+1)>>1;
ri[i] = (ri[i<<1|1]+1)>>1;
}
int res = 0;
for( int i = 0;i < n-1;i++ ){
if( le[i] + ri[i+1] == n && (le[i]&1) ) res++;
}
return res;
}
int NumOfAxisOfSymmetry(const VEC ps[], int n) {
assert(n >= 3);
static LT ha[MAXN << 1];
ha[0] = (ps[0] - ps[n-1]).len2();
ha[1] = ((ps[0] - ps[n-1]) ^ (ps[1] - ps[0]));
for (int i = 1; i < n; ++i) {
ha[i << 1] = (ps[i] - ps[i-1]).len2();
ha[i << 1 | 1] = (ps[i] - ps[i-1]) ^ (ps[Add(i+1, n)] - ps[i]);
}
#if DEBUG
for (int i = 0; i < (n << 1); ++i) {
printf("%d ", ha[i]);
}
putchar('\n');
#endif
return NumOfPalindromeSplit(ha, n << 1);
}
int main() {
static VEC ps[MAXN];
int T;
cin >> T;
while (T--) {
int n;
cin >> n;
for (int i = 0; i < n; ++i) {
ps[i].input();
}
printf("%d\n", NumOfAxisOfSymmetry(ps, n));
}
return 0;
}