a,b,c三根木棍能够增长三个不一样的数字,aa,bb,cc,且aa+bb+cc<=L,问能构成三角形的木棒有多少种方案c++
若是咱们直接考虑把L分配给aa,bb,cc好像很差下手ide
因此逆向考虑spa
合法的状况 = 全部状况 - 不合法的状况.net
首先计算全部的状况code
假设L当时为lblog
咱们把长度为l分配去的总的方案get
这个问题咱们等效为:有三个篮子,每一个篮子放至少一个个物品,总共l个物品,问有多少种方案class
咱们用插板法解决这个问题sed
由于每一个篮子放至少一个,而咱们的目标是能够放0个,怎么办呢?im
咱们能够增长几个物品使初始每一个篮子中就有一个,这里假设有m个篮子,n个物品
那咱们的物品个数变为n+m,这时候会产生n+m-1个隔板
而后咱们要选出m部分来,也就是放m-1个隔板
此时的方案为C(n+m-1,m-1)
回到这个题目
此时长度为l时,方案为C(l+3-1,3-1)
而后咱们枚举一遍l,求和算出总的方案
因此获得为l的时候方案为C(l+2,2)
求不合法的方案==
假设a+aa,b+bb,c+cc(aa,bb,cc分别为分配的增长的长度)
假设a+aa是那条最长的边
此时不合法须要知足以下条件:
b+bb+c+cc<=a+aa
bb+cc<=l-aa
得
bb+cc<=min(l-aa,a-b-c+aa)
令T=bb+cc
这个时候再进行一下问题转化
有T个物品,分配到三个篮子里(能够分配0个)
三个篮子分别是bb,cc和多余的部分
回到上面的插板法同样的解法C(t+3-1.3-1)
而后用总的减去不合法就ok了
ll b,c,a,l; int main() { a=read(),b=read(),c=read(),l=read(); ll zong = (l+1)*(l+2)*(l+3)/6ll; ll no; for(int aa=0 ; aa<=l ; aa++) { ll t = min(l-aa,a-b-c+aa); if(t<0) continue; no = (t+2)*(t+1)/2ll; zong-=no; } for(int bb=0 ; bb<=l ; bb++) { ll t = min(l-bb,b-a-c+bb); if(t<0) continue; no = (t+2)*(t+1)/2ll; zong-=no; } for(int cc=0 ; cc<=l ; cc++) { ll t = min(l-cc,c-b-a+cc); if(t<0) continue; no = (t+2)*(t+1)/2ll; zong-=no; } out(zong); return 0; }