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

给你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; 
} 



你可能感兴趣的:(CF#317-C. Lengthening Sticks-组合数学)