Codeforces Round #317 [AimFund Thanks-Round] (Div. 2) C(组合数+容斥)

来源:互联网 发布:猎巫运动知乎 编辑:程序博客网 时间:2024/06/02 09:14

题目地址:Lengthening Sticks
题意:给出a,b,c,L,要求a+x,b+y,c+z构成三角形,x+y+z<=L,问有多少中分法(x,y,z可为0)。
思路:用容斥来搞,结果ans=全部组合的情况-不符合三角形定理的情况。
1.求全部组合的情况:
当L=0时,res=1;
当L=1时,res=3;所以当L=1时形成的情况为1+3=4
当L=2时,res=6;所以当L=2时形成的情况为4+6=10
当L=3时,res=10; 所以当L=3时形成的情况为10+10=20
……..
所以由上面可以推出当L=n时,全部的组合情况是C(n+3,3)。
2.不符合三角形定理的情况:
如果要形成一个三角形,那么必须任意两边之和大于第三边。那么不符合的就是任意一边大于等于其余两边的和。所以分别把a,b,c当成第三边,然后再考虑将剩下的l拆分三份分配给a,b,c依旧不满足的情况即可。
我们先把a当成第三边,然后给a增加一个La,现在i=a+La,Max=a+b+c+L。现在我们考虑b+c的范围,因为是不满足的情况,所以b+c的变化范围<=i,又因为总长度Max的限制,b+c<=Max-i,所以b+c的最大变化范围只能在min(i,Max-i)。令x=min(i,Max-i)-b-c表示总共变化量的大小,即Lb+Lc<=x,等价于tmp+Lb+Lc的方案数。

#include <stdio.h>#include <math.h>#include <string.h>#include <stdlib.h>#include <iostream>#include <sstream>#include <algorithm>#include <set>#include <queue>#include <stack>#include <map>using namespace std;typedef long long LL;const int inf=0x3f3f3f3f;const double pi= acos(-1.0);const double esp=1e-6;using namespace std;const int Maxn=1e5+10;LL Ex(LL a,LL b,LL c,LL L){    LL res=0;    LL Max=a+b+c+L;    for(LL i=a;i<=L+a;i++){        if(b+c>i) continue;        else{            LL x=min(i,Max-i)-b-c;            res+=(x+2)*(x+1)/2;        }    }    return res;}int main(){    LL a,b,c,L;    LL ans;    while(~scanf("%lld %lld %lld %lld",&a,&b,&c,&L)){        ans=(L+3)*(L+2)*(L+1)/6;        //printf("%lld\n",ans);        ans-=Ex(a,b,c,L);        //printf("%lld\n")        ans-=Ex(b,a,c,L);        ans-=Ex(c,a,b,L);        printf("%lld\n",ans);    }    return 0;}
2 0
原创粉丝点击