BZOJ_1800_[Ahoi2009]fly 飞行棋_乱搞

Posted fcwww

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ_1800_[Ahoi2009]fly 飞行棋_乱搞相关的知识,希望对你有一定的参考价值。

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 飞行棋_乱搞的主要内容,如果未能解决你的问题,请参考以下文章

bzoj 1800: [Ahoi2009]fly 飞行棋

bzoj1800: [Ahoi2009]fly 飞行棋(乱搞)

bzoj1800: [Ahoi2009]fly 飞行棋

bzoj千题计划174:bzoj1800: [Ahoi2009]fly 飞行棋

BZOJ 1800 [Ahoi2009]fly 飞行棋

BZOJ 1800: [Ahoi2009]fly 飞行棋思维题,n^4大暴力