码迷,mamicode.com
首页 > 其他好文 > 详细

BZOJ_1800_[Ahoi2009]fly 飞行棋_乱搞

时间:2018-03-30 21:48:59      阅读:142      评论:0      收藏:0      [点我收藏+]

标签:tput   范围   while   main   结果   amp   技术分享   顺序   image   

BZOJ_1800_[Ahoi2009]fly 飞行棋_乱搞

Description

给出圆周上的若干个点,已知点与点之间的弧长,其值均为正整数,并依圆周顺序排列。 请找出这些点中有没有可以围成矩形的,并希望在最短时间内找出所有不重复矩形。

Input

第一行为正整数N,表示点的个数,接下来N行分别为这N个点所分割的各个圆弧长度

Output

所构成不重复矩形的个数

Sample Input

8
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);
}

 

 

BZOJ_1800_[Ahoi2009]fly 飞行棋_乱搞

标签:tput   范围   while   main   结果   amp   技术分享   顺序   image   

原文地址:https://www.cnblogs.com/suika/p/8678074.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!