acmer
来自大白的渴望

问题 L: 寄蒜几盒?

题目描述

现在有一个圆圈,圆圈上有若干个点,请判断能否在若干个点中选择三个点两两相连组成一个等边三角形? 
这若干个点在圆圈上按顺时针顺序分布。 
如果可以的话输出"Yes"(不含引号)
不可以的话输出"No"(不含引号)
 
输入

第一行一个整数n,表示圆圈上有n个点
第二行n个整数,分别表示第1个点与第2个点之间圆弧的长度、第2个点与第3个点之间圆弧的长度······第n个点与第1个点之间圆弧的长度
3 <= n <= 10^6
1 <= x_i <= 1000 ( 1 <= i <= n)
输出

如果可以组成等边三角形则输出"Yes"(不含引号)
否则输出"No"(不含引号)
样例输入

样例输入1:
4
1 1 2 2

样例输入2:
8
4 2 4 2 2 6 2 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代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 using namespace std;
 4 const int maxn=1e6+10;
 5 
 6 int n;
 7 int a[maxn];
 8 int sum[maxn];
 9 
10 bool isSat(int p1,int p2){//判断p1,p2点是否在范围内
11     return p1 <= sum[n] && p2 <= sum[n];
12 }
13 bool Check(int p1)//二分查找
14 {
15     int l=0,r=n+1;
16     while(r-l > 1)
17     {
18         int mid=l+((r-l)>>1);
19         if(sum[mid] == p1)
20             return true;
21         if(sum[mid] < p1)
22             l=mid;
23         else
24             r=mid;
25     }
26     return false;
27 }
28 char *Solve()
29 {
30     if(sum[n]%3 != 0)//特判
31         return "No";
32     int d=sum[n]/3;
33     for(int i=1;i <= n;++i)//遍历所有点,判断是否含有满足条件的三个点
34     {
35         int p1=sum[i]+d,p2=sum[i]+2*d;
36         if(isSat(p1,p2) && Check(p1) && Check(p2))//二分查找点p2,p2是否存在
37             return "Yes";//如果存在,返回"Yes"
38     }
39     return "No";
40 }
41 int main()
42 {
43     scanf("%d",&n);
44     sum[0]=0;
45     for(int i=1;i <= n;++i)
46         scanf("%d",a+i),sum[i]=sum[i-1]+a[i];//前缀和
47 
48     printf("%s\n",Solve());
49 }
View Code

  对算法时间复杂度的分析:

    每遍历一个点都需要log(n)的复杂度查找是否含有p1,p2点,一共遍历了n个点,所以总的时间复杂度为O( nlog(n) ),106完全可以过。

 

posted on 2018-11-26 14:41 hyacinthLJP 阅读(...) 评论(...) 编辑 收藏