寄蒜几盒?

原题

题目描述
现在有一个圆圈,圆圈上有若干个点,请判断能否在若干个点中选择三个点两两相连组成一个等边三角形?
这若干个点在圆圈上按顺时针顺序分布。
如果可以的话输出"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

提示
对于样例2配图:

感慨

又一次被题目吓破了胆。。。实际上这个题还是挺简单的(看了凯哥的题解。。)

解法

①既然要找到圆内是否有等边三角形,那么就应该从等边三角形的性质入手,如果为等边三角形那么这三个三角形的顶点一定三等分圆弧

②有了①的结论那么这个题就好做多了。首先我们可以把圆看成一条直线,圆上的点可以映射为直线上的点,二维变一维

③之后我们把每个出现的点都用桶去记录,这里好像因为数据大小的问题还是开map比较保险,毕竟re还是罚时不少的

④然后记录每一个点的坐标,再记录好三等分圆弧的量,然后寻找是否有这样的点即可

⑤这里有一个小结论就是如果直线的长度%3不等于0的话,那么可以直接判断为没有,不过数据好像不强这个地方没有考虑到

代码

#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/hash_policy.hpp>
using namespace std;
using namespace __gnu_pbds;
typedef long long ll;
gp_hash_table <ll,ll> bk,x;
ll pt,n;
int main()
{
  ios::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  cin>>n;
  for(int i=0;i<n;i++)
  {
    int t;
    cin>>t;
    bk[pt]=1;
    x[i]=pt;
    pt+=t;
  }
  if(pt%3!=0)
  return cout<<"No",0;
  ll r=pt/3;
  for(int i=0;i<n;i++)
  {
    ll x1=x[i]+r;
    ll x2=x[i]+r+r;
    if(bk[x1]&&bk[x2])
    return cout<<"Yes",0;
    if(x1>=pt||x2>pt)
    break;
  }
  cout<<"No";
}
原文地址:https://www.cnblogs.com/baccano-acmer/p/10028992.html