给你a,b,c木棒的长度,给你一个额外长度L
你可以给abc随意增加长度x y z(x+y+z《L,xyz可为0) 使得 abc构成一个三角形
首先,枚举合法的三角形肯定是超时的,正难则反,那么我们可以先计算出总共的方案数,以及不合法的三角形方案数,相减便是合法的了;
1、首先枚举 你 增加了的总长度为j (一定增加了j,不多不少), j范围是0到L
对每一个j, 都有 方案数+=(j+1)(j+2)/2; 显然根据隔板法,是j+1个空位插2个木板、 (+1是两个木板都在左右端点的情况,也就是分别增加0 0 j)
先累计求出总的方案数
2、现在计算不合法方案,还是枚举 你 增加了的总长度为j (一定增加了j,不多不少), j范围是0到L
对每一个j,我们设 a木板最终是最长的木板,a增加了长度L-t1, 那么需要满足两边之和大于第三边的条件,即 a+L-t1<b+c+t1;
因此,不能构成三角形的条件就是 a+L-t1》b+c+t1; 也即是 t1<= (L+a-b-c)/2 ;
就是说,如果t1《(L+a-b-c)/2 ; 那么这个三角形便不合法;
令k=(L+a-b-c)/2; 由于自动取整的关系,所以得到的k就是最接近(L+a-b-c)/2的整数;
其表示意义为(a最终为最长木板的条件下,如果a增加了L-k以上的长度,所构成的三角形是不合法的)
也就是只要t1<=k都是不合法的;
那么不合法的三角形个数为 cun1=(k+1)(k+2)/2; //意思是 把分配给a后剩下的长度 再分给a,b,c,三人的方案数(不合法方案数);
/////////////////////////////////////////////
有一点要注意的是
因为t1<=k的三角形都是不合法的,所以:
如果得到k<0,那么说明分配总长度为j时,怎么分配都是合法的(因为t1范围是0到J,所以t1取到的都是构成合法三角形的值)
如果k>j,那么说明怎么分配都是不合法的,因为(因为t1范围是0到J,所以t1去到的三角形总是不合法的)
/////////////////////////////////////////////
同理,我们还要 计算 最终b、c分别 为最长木板的情况,方法和a一样, 最后我们就得到了所有的不合法方案数
最后 总-不合法=合法 ;
#include<cstdio> #include<cstring> #include<cmath> #include<cstdlib> #include<iostream> #include<algorithm> #include<map> using namespace std; int main() { __int64 a,b,c,l; __int64 j; __int64 i; while(scanf("%I64d%I64d%I64d%I64d",&a,&b,&c,&l)!=EOF) { __int64 ans=0; for( i=0;i<=l;i++) ans+=(i+1)*(i+2)/2; __int64 cun1=0; __int64 cun2=0; __int64 cun3=0; for(j=0;j<=l;j++) { __int64 t1=(c-a-b+j)/2; __int64 t2=(b-a-c+j)/2; __int64 t3=(a-c-b+j)/2; if (t1>j) t1=j; if (t2>j) t2=j; if (t3>j) t3=j; if (c-a-b+j<0) //因为如果c-a-b+j==-0.5时,-0.5/2=0,不是我们想要的 cun1+=0; else cun1+= (t1+1)*(t1+2)/2 ; if (b-a-c+j<0) cun2+=0; else cun2+= (t2+1)*(t2+2)/2 ; if (a-c-b+j <0) cun3+=0; else cun3+= (t3+1)*(t3+2)/2 ; } printf("%I64d\n",ans-cun1-cun2-cun3); } return 0; }