题意是一个圆上,给出n个点之间的距离,最后的距离是最后一个点跟第一个点之间的距离,问能组成多少个等边三角形。
容易想到圆的周长不能整除3的话一定无法构成等边三角形,所以先特判这种情况。然后可以发现,每条线段必定是n个连续的点,这样可以找到2*n个点,判断从当前点开始,能否在n个点之内,正好找到3段长度有多少种,时间复杂度是O(n*n),需要优化,建立前缀和数组,二分查找当前前缀和+sum/3的数的坐标,大于i+n就跳出循环,最后得到的数要整除3,如 3 4 2 1 5 3,计算的是 4 2 1 5 3 3,1 5 3 3 4 2,3 3 4 2 1 5。有重复计算。
代码实现:
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=1e6+5;
int a[maxn];
ll pre[maxn*2];
int main()
{
int n,i,j,k;
scanf("%d",&n);
ll sum=0;
for(i=0;i<n;i++)
{
scanf("%d",&a[i]),sum+=a[i];
a[i+n]=a[i];
}
pre[0]=a[0];
for(i=1;i<2*n;i++)
pre[i]+=pre[i-1]+a[i];
if(sum%3)
{
printf("0\n");
return 0;
}
ll t=sum/3,s=0,temp;
for(i=0;i<n;i++)
{
ll c;
if(i)
c=pre[i-1]+t,temp=i-1;
else
c=t,temp=i;
bool flag=0;
int x=lower_bound(pre,pre+2*n,c)-pre;//cout<<x<<' ';
if(x>=i+n)
flag=1;
if(flag)
continue;
c=pre[x]+t;temp=x;
x=lower_bound(pre,pre+2*n,c)-pre;//cout<<x<<' ';
if(x>=i+n)
flag=1;
if(flag)
continue;
c=pre[x]+t;temp=x;
x=lower_bound(pre,pre+2*n,c)-pre;//cout<<x<<"****"<<endl;
if(x>=i+n)
flag=1;
if(flag)
continue;
if(!flag)
s++;
}
printf("%lld\n",s/3);
}