题目链接:http://bestcoder.hdu.edu.cn/contests/contest_chineseproblem.php?cid=575&pid=1002
刚开始拿到这题一点头绪也没有,看了题解,也不太能理解,只知道枚举个什么东东,看了别人AC的代码,大概知道思路了,就是推出前半段长为x,后半段长为y,且可以组成三角形的种数的一个公式就可了。
推导思路:假设前半段长为x,后半段为y,则可以把后半段y分为a,b两段。则就有:
一:x>=y时,种数为0
二:y>x时,b=y-a,所以可得不等式组:
1:a+b=y>x
2:x+a>b
3:x+b>a
接下来,把b=y-a带进去并解不等式组,可得到:(x+y)/2>a>(y-x)/2,到了这里,可以看出x和y是已知的,那么a的范围就求出来了,也就是所能组成的三角形的种数也就是它了。
代码:
#include<iostream>
#include<sstream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<set>
#include<map>
#include<queue>
#include<vector>
#include<string>
#define LL long long
#define INF 0x7fffffff
using namespace std;
int n,m;
LL ans;
void dfs(int x,int y){
if(x>=y) return;
int l,r;
if((y+x) & 1) r=(y+x)/2;
else r=(y+x)/2-1;
r=min(r,y-1);//求出分析中a的上界
l=max(1,(y-x)/2+1);//求出分析中a的下界,下界至少为1
ans+=max(r-l+1,0);
}
int main(){
while(cin>>n){
cin>>m;
int Min=INF,Max=-1;
int t;
for(int i=0;i<m;i++) {
cin>>t;
Min=min(Min,t);
Max=max(Max,t);
}
int L=Min-1,R=n-Max;//分别获取左右的剩余的长度
if(L==R) {cout<<0<<endl;continue;}
ans=0;
if(L && R){
dfs(min(L,R),max(L,R));//只能拆分长的那段
printf("%lld\n",ans);
continue;
}
t=max(L,R);
for(int i=1;i<t;i++)
dfs(i,t-i);
printf("%lld\n",ans);
}
return 0;
}