BZOJ1800 fly 飞行棋 [几何]

f l y   飞 行 棋 fly\ 飞行棋 fly 

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

N ≤ 25 N \le 25 N25 .


最 初 想 法 \color{blue}{最初想法}

发现数据范围很小, 首先就想到 O ( N 2 ) O(N^2) O(N2) 枚举端点, 然后检查关于直径对称的对应端点是否存在,
但是发现这样去作关于直径对称的线段很麻烦, 作罢 .


正 解 部 分 \color{red}{正解部分}

矩形的四个角都为直角, 而直角所对弦长为直径, 直径所对弧长为周长的一半,
所以满足条件的矩形的对角线就对应直径, 于是考虑 枚举 对角线, 使用对角线去 " 拼 " "拼" "" 矩形 .
于是枚举 i , j i, j i,j 两个端点, 判断其距离 t t t 是否满足 t = d 2 t = \frac{d}{2} t=2d, 若满足, 则说明发现了一条新的对角线. ( d 为 周 长 ) (d为周长) (d)

最后得到对角线的个数为 c n t cnt cnt 个, 取出其中 2 2 2 个构成一个矩形, 则答案为 C c n t 2 = 1 2 c n t ( c n t − 1 ) C_{cnt}^2=\frac{1}{2}cnt(cnt-1) Ccnt2=21cnt(cnt1) .

时间复杂度 O ( N 2 ) O(N^2) O(N2) .


实 现 部 分 \color{red}{实现部分}

  • 注意圆的周长可能是奇数 .
#include<bits/stdc++.h>
#define reg register

const int maxn = 25;

int N;
int d;
int cnt;
int A[maxn];

int main(){
        scanf("%d", &N);
        for(reg int i = 1; i <= N; i ++) scanf("%d", &A[i]), d += A[i], A[i] += A[i-1];
        for(reg int i = 1; i <= N; i ++)
                for(reg int j = i+1; j <= N; j ++)
                        if((abs(A[i]-A[j])<<1) == d) cnt ++;
        printf("%d\n", cnt*(cnt-1)>>1);
        return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值