CF#317-C. Lengthening Sticks-组合数学

来源:互联网 发布:不持有的生活 知乎 编辑:程序博客网 时间:2024/05/17 08:02

给你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;elsecun2+= (t2+1)*(t2+2)/2 ;  if (a-c-b+j <0)cun3+=0;elsecun3+=  (t3+1)*(t3+2)/2 ; }printf("%I64d\n",ans-cun1-cun2-cun3); } return 0; } 



0 0
原创粉丝点击