BZOJ1800: [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
题解Here!
本来以为是个啥计算几何。。。
一看$n<=20$,woc,不会是状压吧。。。
吓得一直不敢做。。。
直到在洛谷上发现这题是普及难度。。。
我才发现这就是一沙茶题。。。
圆学过没?知道一个圆的内接直角三角形的斜边是圆的直径不?
那就好了。
我们搞一个弧长前缀和$val[i]$,再算一个周长$sum$。
枚举两个点$i,j$,若$val[j]-val[i]==\frac{sum}{2}$,即弧长等于周长的一半,那么说明这个角是直角。
计算出直角的数量$ans$,答案就是$\left(\begin{array}{c} ans \\ 2 \end{array} \right)$,即常说的$C_{ans}^2=\frac{ans\times (ans-1)}{2}$。
附代码:
#include<iostream> #include<algorithm> #include<cstdio> #define MAXN 30 using namespace std; int n,sum=0,ans=0,val[MAXN]; inline int read(){ int date=0,w=1;char c=0; while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();} while(c>='0'&&c<='9'){date=date*10+c-'0';c=getchar();} return date*w; } int main(){ n=read(); val[0]=0; for(int i=1;i<=n;i++){ int x=read(); val[i]=val[i-1]+x; sum+=x; } for(int i=1;i<=n;i++) for(int j=i+1;j<=n;j++) if(val[j]-val[i]==sum/2)ans++; printf("%d\n",ans*(ans-1)/2); return 0; }