您的位置:首页 > 其它

Codeforces 571A 容斥

2015-08-23 13:53 246 查看
Codeforces 571A

题目链接:
http://codeforces.com/problemset/problem/57
题意:

给三根棍子,长度分别为a,b,c。现有长度L,可使三根棍子的长度任意增加且增加总和小于等于L。问有多少种增加方案。

思路:

感谢http://blog.csdn.net/stl112514/article/details/47904301

容斥,即用增加综总和小于等于L的方案总数减去不合法数。总数C(L+3,3),这是一个合成公式。具体是C(2,2)+C(3,2)+C(4,2)+...+C(L,2)。这个公式又是怎么得出来的,假设当前棍子长度增加综合为i,则有C(i+2,2)种选择方案(有i+2个空可以选,而选择是有序的,因为第一根棍子选择的切点必须在第二个前面,但是可以同时选一个空)。

不合法数。枚举以哪一条边作为最大第三边(设为a),先把它加成最大第三边,用去长度i(i>=0)。然后枚举它长度是a+i, a+i+1,....a+L的情况。此时假设当前用去长度i,则最大可用剩余长度是min( L - i, a + i - b - c),这个应该不需要解释。然后在这些长度里面任意分配,用到之前C(i+2,2)的公式。

这里可能不合法数计算会有出现重复情况的疑惑。刚刚写了一大版全删了。。。最大边都不一样怎么会重,对于一个确定最大边的情况,函数里面枚举的是另外两条边分配剩余长度且仍旧不合法的方案数。

源码:

#include <cstdio>

#include <cmath>

#include <cstring>

#include <algorithm>

#include <string>

#include <iostream>

using namespace std;

#define LL long long

#define gmax(a,b) ((a) > (b) ? (a) : (b))

#define gmin(a,b) ((a) < (b) ? (a) : (b))

LL cal(LL a, LL b, LL c, LL l)

{

// printf("a = %I64d, b = %I64d, c = %I64d\n", a, b, c);

LL ans = 0;

for(int i = gmax(0, b + c - a) ; i <= l ; i++){

int x = gmin(l - i , a + i - b - c);

ans += (LL)(x + 1) * (x + 2) / 2;

}

// printf("ans = %I64d\n", ans);

return ans;

}

int main()

{

LL a, b, c, l;

while(scanf("%I64d%I64d%I64d%I64d", &a, &b, &c, &l) != EOF){

LL ans = (LL)(l + 3) * (l + 2) / 2 * (l + 1) / 3;

ans -= cal(a, b, c, l);

ans -= cal(b, c, a, l);

ans -= cal(c, a, b, l);

printf("%I64d\n", ans);

}

return 0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: