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