1.题目描述:点击打开链接
2.解题思路:本题利用减法原理解决。比赛时候暴力枚举果断超时==。正确的做法是用总体方案-不合理的方案数。显然,总体方案的个数等价于求解x1+x2+x3+x4=l的非负整数解的个数,利用组合数学的结论等于C(l+4-1,4-1)=C(l+3,3)。其中x4表示没有使用的长度,它从0取到l。接下来就是考虑不合理的方案数目。我们先考虑让a增加一个La,变成a+La,我们令i=a+La,maxsum=a+b+c+l,这时我们考虑b+c的变化范围,显然b+c不能超过i,又由于总长maxsum的限制,b+c不能超过maxsum-i,因此b+c最大只能变化到min(i,maxsum-i),令x=min(i,maxsum-i)-b-c+1,表示总共的变化量大小。即Lb+Lc≤x,这个式子的方案数等价于Lb+Lc+tmp=x的方案数,类似于前面的讨论,等于C(x+3-1,3-1)=C(x+2,2)=(x+2)(x+1)/2。即第一种不合理的方案数是(min(i,maxsum-i)-b-c+1)*(min(i,maxsum-i)-b-c+2)/2。同理可以找到b,c的不合理方案数,最后减去它们就是答案。
3.代码:
//#pragma comment(linker, "/STACK:1024000000,1024000000") #include<iostream> #include<algorithm> #include<cassert> #include<string> #include<sstream> #include<set> #include<bitset> #include<vector> #include<stack> #include<map> #include<queue> #include<deque> #include<cstdlib> #include<cstdio> #include<cstring> #include<cmath> #include<ctime> #include<cctype> #include<functional> using namespace std; #define me(s) memset(s,0,sizeof(s)) #define rep(i,n) for(int i=0;i<(n);i++) typedef long long ll; typedef unsigned int uint; typedef unsigned long long ull; typedef pair <int, int> P; ll a,b,c,l; int main() { while(cin>>a>>b>>c>>l) { ll ans=0; ll maxsum=a+b+c+l; for(ll i=a;i<=a+l;i++) if(b+c>i)continue; //i表示a刚刚不能构成三角形的长度 else { ans+=(min(i,maxsum-i)-b-c+1)*(min(i,maxsum-i)-b-c+2)/2;//Lb+Lc的可变范围是0~min(i,maxsum-i)-b-c,有min(i,maxsum-i)-b-c+1个值 } for(ll i=b;i<=b+l;i++)//同上 if(a+c>i)continue; else ans+=(min(i,maxsum-i)-a-c+1)*(min(i,maxsum-i)-a-c+2)/2; for(ll i=c;i<=c+l;i++) if(b+a>i)continue; else ans+=(min(i,maxsum-i)-b-a+1)*(min(i,maxsum-i)-b-a+2)/2; printf("%I64d\n",(l+1)*(l+2)*(l+3)/6-ans); //总方案数是C(l+3,3) } }