2018.11.26 QLU新生赛部分题解
问题 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
题解:
预备知识补充:
(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 }
对算法时间复杂度的分析:
每遍历一个点都需要log(n)的复杂度查找是否含有p1,p2点,一共遍历了n个点,所以总的时间复杂度为O( nlog(n) ),106完全可以过。