绳子对折
题目描述
FJ 有一个长度为L(1<= L <= 10,000)的绳子。 这个绳子上有N(1 <= N <= 100)个结,包括两个端点。 FJ想将绳子对折,并使较短一边的绳子上的结与较长一边绳子上的结完全重合,如图所示:
找出FJ有多少种可行的折叠方案。
输入格式
第一行: 两个整数, N和L
第2至N+1行: 每一行包含一个整数表示一个结所在的位置,总有两个数为0和L
输出格式
第一行: 一个整数表示FJ可折叠的方案数。
样例 #1
样例输入 #1
5 10 0 10 6 2 4
样例输出 #1
4
提示
(可在1,2,3,8点处折叠)
题解:
#include <bits/stdc++.h>
using namespace std;
int n,m,ans=0;
set<int> a;
void flr(auto l,auto r)
{
int mid= (*l+*r)/2; //折叠处为mid
int flag=1; //标记
if(r==a.end()||l==a.end()||mid==0||mid==m*2) return; //地址不存在、或者折叠处为两端
while(l!=a.end() && r!=a.end()){
if(*r-mid == mid-*l) { //如果对称,则继续左右遍历
r++;
l--;
} else {
flag=0;
return;
}
}
if(flag) ans++;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=0;i<n;i++){
int x;
scanf("%d",&x);
a.insert(2*x); //防止出现小数
}
for(auto i=a.begin();i!=a.end();i++){ //遍历每个绳结
flr(i,i); //查找结点处是否可折
auto r=i,l=r++;
flr(l,r); //查找非结点处是否可折
}
printf("%d\n",ans);
return 0;
}