1. 程式人生 > >[BZOJ1100][POI2007]對稱軸osi

[BZOJ1100][POI2007]對稱軸osi

{} const std include 角度 rip 一個 flag opera

1100: [POI2007]對稱軸osi

Time Limit: 10 Sec Memory Limit: 162 MB Submit: 716 Solved: 279 [Submit][Status][Discuss]

Description

FGD小朋友——一個聞名遐邇的年輕數學家——有一個小MM,yours。FGD小朋友非常喜歡他的MM,所以他很樂 意幫助他的MM做數學作業。但是,就像所有科學的容器一樣,FGD的大腦拒絕不停地重復思考同樣的問題。不幸的 是,yours是一個十分用功的學生,所以她不停地讓FGD幫助她檢查她的作業。一個陽光明媚的周末,yours的數學 老師布置了非常多的尋找多邊形的對稱軸的題,足夠她做相當長的一段時間了。在此之前FGD已經決定去海邊度過 這個難得的假期,不過他還是覺得應該幫助他的MM對付可愛的數學作業。很快地,他找到了解決方案,最好寫一個 程序來幫助yours檢查她的數學作業。因為FGD並非一個計算機科學家,所以他找到了他的好朋友你,請你幫助他完 成這個任務。請寫一個程序:讀入多邊形的描述計算出每個多邊形的對稱軸數將計算的結果輸出

Input

  輸入的第一行包含一個正整數t(1<=t<=10),為多邊形的邊數。接下來,為t個多邊形的描述,每個描述的第一 行為一個正整數n(3<=n<=100000),表示了多邊形的點數。然後在後面n行每行兩個整數x和y(?100000000<=x, y<=1 00000000),依次表示多邊形的頂點坐標。多邊形不一定是凸的,但是不自交——任何兩條邊都只有最多一個公共 點——他們的公共端點。此外,沒有兩條連續的邊平行。

Output

  你的程序應該輸出正好t行,第k行包含了一個整數nk——表示第k個多邊形有多少個對稱軸。

Sample Input

2
12
1 -1
2 -1
2 1
1 1
1 2
-1 2
-1 1
-2 1
-2 -1
-1 -1
-1 -2
1 -2
6
-1 1
-2 0
-1 -1
1 -1
2 0
1 1

Sample Output

4
2

HINT

技術分享

乍一看是計算幾何,結果是字符串。。。

把邊長和角度存起來,然後找最長回文串即可。。。

角度的話會被卡精度,所以用叉積代替

#pragma GCC optimize("O2")
#include <cstdio>
char buf[20000000], *ptr = buf - 1;
inline int readint(){
    int n = 0;
    bool flag = false;
    while(*++ptr < 0 || *ptr > 9) if(*ptr == -) flag = true;
    
while(*ptr <= 9 && *ptr >= 0) n = (n << 1) + (n << 3) + (*ptr++ & 15); return flag ? -n : n; } template <typename _Tp> inline _Tp min_(const _Tp &a, const _Tp &b){ return a < b ? a : b; } typedef long long ll; const int maxn = 100000 + 10; struct Poi{ ll x, y; Poi(){} Poi(ll _x, ll _y): x(_x), y(_y){} Poi operator - (const Poi &a){ return Poi(x - a.x, y - a.y); } }p[maxn]; inline ll sqr(const ll &x){ return x * x; } inline ll dis(const Poi &a, const Poi &b){ return sqr(a.x - b.x) + sqr(a.y - b.y); } inline ll cross(const Poi &a, const Poi &b){ return a.x * b.y - a.y * b.x; } int n; ll s[maxn * 3]; int r[maxn * 3]; void work(){ n = readint(); for(int i = 1; i <= n; i++){ p[i].x = readint(); p[i].y = readint(); } p[0] = p[n]; p[n + 1] = p[1]; for(int i = 1; i <= n; i++){ s[i * 2 - 1] = cross(p[i - 1] - p[i], p[i + 1] - p[i]); s[i * 2] = dis(p[i], p[i + 1]); } int len = n + n; for(int i = 1; i <= n; i++) s[i + len] = s[i]; len = len + n; int mx = 0, id = 0, ans = 0; for(int i = 1; i <= len; i++){ if(mx > i) r[i] = min_(r[2 * id - i], mx - i); else r[i] = 1; while(i - r[i] > 0 && i + r[i] <= len && s[i - r[i]] == s[i + r[i]]) r[i]++; if(r[i] + i > mx){ mx = r[i] + i; id = i; } if(r[i] > n) ans++; } printf("%d\n", ans); } int main(){ fread(buf, sizeof(char), sizeof(buf), stdin); int T = readint(); while(T--) work(); return 0; }

[BZOJ1100][POI2007]對稱軸osi