问题 L: 寄蒜几盒? 题目描述 现在有一个圆圈,圆圈上有若干个点,请判断能否在若干个点中选择三个点两两相连组成一个等边三角形?
这若干个点在圆圈上按顺时针顺序分布。
如果可以的话输出"Yes"(不含引号)
不可以的话输出"No"(不含引号) 输入 第一行一个整数n,表示圆圈上有n个点
第二行n个整数,分别表示第1个点与第2个点之间圆弧的长度、第2个点与第3个点之间圆弧的长度······第n个点与第1个点之间圆弧的长度
<= n <= ^
<= x_i <= ( <= i <= n)
输出 如果可以组成等边三角形则输出"Yes"(不含引号)
否则输出"No"(不含引号)
样例输入 样例输入1: 样例输入2: 样例输出 样例输入1:
Yes 样例输入2:
Yes
题目描述(L: 寄蒜几盒?)
题解:
预备知识补充:
(1):在同圆或等圆中,相同的圆心角对应的弦相等,对应的弧也相等。L: 寄蒜几盒?
会了这个知识,那这道题差不多就做出来了。
相关变量解释:
sum[maxn]:..................................sum[ i ]表示第1个点距第i+1个点的距离 ,也就是前缀和。
步骤:
(1):特判圆周长sum[ n ]是否整除3,如果不整除,直接输出"No"。
(2):如果sum[ n ]整除3,遍历一遍数组,判断是否含有三点a,b,c,使得ab,bc,ca间的距离等于sum[ n ]/3,如果有,输出"Yes",否则输出"No"。
AC代码:
#include<iostream>
#include<cstdio>
using namespace std;
const int maxn=1e6+; int n;
int a[maxn];
int sum[maxn]; bool isSat(int p1,int p2){//判断p1,p2点是否在范围内
return p1 <= sum[n] && p2 <= sum[n];
}
bool Check(int p1)//二分查找
{
int l=,r=n+;
while(r-l > )
{
int mid=l+((r-l)>>);
if(sum[mid] == p1)
return true;
if(sum[mid] < p1)
l=mid;
else
r=mid;
}
return false;
}
char *Solve()
{
if(sum[n]% != )//特判
return "No";
int d=sum[n]/;
for(int i=;i <= n;++i)//遍历所有点,判断是否含有满足条件的三个点
{
int p1=sum[i]+d,p2=sum[i]+*d;
if(isSat(p1,p2) && Check(p1) && Check(p2))//二分查找点p2,p2是否存在
return "Yes";//如果存在,返回"Yes"
}
return "No";
}
int main()
{
scanf("%d",&n);
sum[]=;
for(int i=;i <= n;++i)
scanf("%d",a+i),sum[i]=sum[i-]+a[i];//前缀和 printf("%s\n",Solve());
}
对算法时间复杂度的分析:
每遍历一个点都需要log(n)的复杂度查找是否含有p1,p2点,一共遍历了n个点,所以总的时间复杂度为O( nlog(n) ),106完全可以过。