BZOJ_1800_[Ahoi2009]fly 飞行棋_乱搞
Description
给出圆周上的若干个点,已知点与点之间的弧长,其值均为正整数,并依圆周顺序排列。 请找出这些点中有没有可以围成矩形的,并希望在最短时间内找出所有不重复矩形。
Input
第一行为正整数N,表示点的个数,接下来N行分别为这N个点所分割的各个圆弧长度
Output
所构成不重复矩形的个数
Sample Input
8
1
2
2
3
1
1
3
3
1
2
2
3
1
1
3
3
Sample Output
3
HINT
N<= 20
分析:此题数据范围较小,有多种做法,这里只考虑O(n)的做法。
首先我们知道矩形的对角线一定是直径。并且不同的直径对应不同的矩形。
转化为两点间弧长为周长的一半的点对个数,然后求Cn2
做法1.双指针,扫一遍就出结果。
2.把弧长哈希,对每个点找一遍。
代码(哈希):
#include <stdio.h> #include <string.h> #include <algorithm> #include <math.h> using namespace std; #define N 100050 #define LL long long int a[N], n, p = 500009; LL s[N], sum, num, now, d, h[500050]; void insert(LL x) { int u = x % p; while(h[u] != -1 && h[u] != x) u = (u + 1) % p; h[u] = x; } bool find(LL x) { int u = x % p; while(h[u] != -1 && h[u] != x) u = (u + 1) % p; return h[u] != -1; } int main() { scanf("%d", &n); memset(h, -1, sizeof(h)); int i, j; for(i = 1;i <= n; ++ i) scanf("%d", &a[i]), s[i] = s[i - 1] + a[i], sum += a[i]; for(i = 1;i <= n; ++ i) insert(s[i] % sum); if(sum % 2) { puts("0"); return 0; } for(i = 1;i <= n; ++ i) num += find((s[i] + sum / 2) % sum); num /= 2; printf("%lld\n", num * (num - 1) / 2); }