传送门 http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1509
现在有三根木棒,他们的长度分别是a,b,c厘米。你可以对他们进行加长(不同的木棒可以增加不同的长度),他们总的加长长度不能超过L厘米。你也可以不对他们进行加长。
现在请你计算一下有多少种加长的方式使得他们能构成合法的三角形(面积非0)。
Input
单组测试数据。 共一行,包含4 个整数a,b,c,L (1≤a,b,c≤3*10^5, 0≤L≤3*10^5)。
Output
输出答案占一行。
Input示例
1 1 1 2
Output示例
4
这个题我被坑了很久,搞了2.5小时以上了才AC,不过AC的时候真TM爽!(然而岑神几分钟就做对了ORZ)其实很早就有思路了,但是计算的公式疏忽了好几个地方,最后还是下载了部分数据才过的
办法是枚举加长a的量(设其为i),剩余的可用长度为w,很容易得出在不考虑构成三角形的情况下,总共有(w+1)*(w+2)/2种方案,如果减去其中不合法的种数就是a加长量为i的时候的合法方案数了。
不合法的方案有3种,a太长,b太长,c太长(这里说的a,b,c是已经加长后的长度)
针对a太长,我们设x=min(w,a+i-b-c),换句话讲,就是即使给b,c加上共计为x的长度,依然不合法,这种情况数为(x+2)*(x+1)/2
针对b太长或者c太长,其实这两种情况是差不多的,我们设x=w+b-a-c-i(b太长),x=w+c-a-b-i(c太长),思路是先假设b被加到了b+w,然后减掉b中的一部分,把那一部分中的一部分加到c上
然后分三种情况讨论
情况一.w<=x/2 也就是就算把原来加到b上去的长度全卸下来,并且全加到c上去,b还是太长,那么这里的操作是ans-=(1+w)*(w+2)/2;
情况二.w>=x 这种情况下w不会限制我们把b的一部分长度卸下来,操作是ans-=(2+x/2)*(1+x/2)/2,ans-=(x-x/2)*(1+x-x/2)/2;
情况三.x/2<w<x 这种情况下w会限制我们把b的一部分长度卸下来,操作是ans-=(2+x/2)*(1+x/2)/2,ans-=(w-x/2)*(x-x/2+x-w+1)/2;
#include<string> #include<cstring> #include<iostream> #include<algorithm> #include<cstdio> #include<cmath> #include<vector> #include<queue> using namespace std; typedef long long ll; int main() { ll i,j; ll a,b,c,L; scanf("%lld%lld%lld%lld",&a,&b,&c,&L); ll ans=0; if(a+b+L<=c||a+c+L<=b||b+c+L<=a) { printf("0\n"); return 0; } for(i=0;i<=L;i++) { ll w=L-i; if(a+i>=b+c+w)break; ans+=(w+1)*(w+2)/2;//√ if(a+i>=b+c) { ll x=min(a-b-c+i,w); ans-=(x+2)*(x+1)/2;//√ } if(w+b>=a+c+i) { ll x=w+b-a-c-i; if(x<=w) { ans-=(2+x/2)*(1+x/2)/2; ans-=(x-x/2)*(1+x-x/2)/2; } else if(w<x) { if(w<=x/2) { ans-=(1+w)*(w+2)/2; } else { ans-=(2+x/2)*(1+x/2)/2; ans-=(w-x/2)*(x-x/2+x-w+1)/2; } } } if(w+c>=a+b+i) { ll x=w+c-a-b-i; if(x<=w) { ans-=(2+x/2)*(1+x/2)/2; ans-=(x-x/2)*(1+x-x/2)/2; } else if(w<x) { if(w<=x/2) { ans-=(1+w)*(w+2)/2; } else { ans-=(2+x/2)*(1+x/2)/2; ans-=(w-x/2)*(x-x/2+x-w+1)/2; } } } } printf("%lld\n",ans); return 0; } /* 17 28 19 5558 */ /* 7396315389 */ /* 100000 300000 100000 100003 */ /* 400012 */