Triangle Counting(uva 11401)

来源:互联网 发布:java工程师好找工作吗 编辑:程序博客网 时间:2024/05/21 10:01

Triangle Counting

You are given n rods oflength 1, 2…,n. You have to pick any 3 of them & build a triangle. How many distincttriangles can you make? Note that, two triangles will be considered differentif they have at least 1 pair of arms with different length.

 

Input

The input for each case will have only asingle positive integer (3<=n<=1000000). The end ofinput will be indicated by a case with n<3. This case should notbe processed.

 

Output

For each test case, print the number ofdistinct triangles you can make.

 

SampleInput                                                 

5

8

0

 

 Output for Sample Input

4

22

 

题意

   从1-n这n个正整数中选出不同的3个数使得它们能构成一个三角形,求所有方案的数量。

 

思路

   计数问题,假设取出的符合要求的三个数为x,y,z且x最大,则有x<y+z,移项得到x-y<z,同时z<x,所以z的取值范围是(x-y,x)。当y==1时,z无解,当y==2时,z有一组解,…当y==x-1时,z有x-2组解,等差数列求和可知共有(x-1)(x-2)/2组解,但是要注意两点:

(1)确定一个y然后计算z的取值范围时z是有可能和y相等的,而尽管满足构成三角形的条件,但是y==z不符合题意(选3个不同的数字),所以要减去这一部分情况,当y>=floor(x/2)+1时,一定有y==z可以构成三角形,y最大到x-1,所以一共有(x-1)-(floor(x/2)+1)+1==x-1-floor(x/2)种y,z相等的情况,要把它们减去。

(2)这里的方案数其实被算了两次,比如x==5时,枚举y==3时z可以是4,但枚举到y==4时z又可以是3,但这是同一种选择情况,所以要在最后的结果中除2。

所以对于某个x,符合要求的情况数为((x-2)*(x-1)/2-(x-1-floor(x/2)))/2,利用递归来求数列的前n项和即可。

 

代码

 

#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>using namespace std;typedef long long ll;const int maxn = 1e6 + 500;ll n;ll s[maxn];void init() {memset(s, 0, sizeof(s));for (ll x = 3; x <= 1e6 + 50; x++) {s[x] = s[x - 1] + ((x - 2)*(x - 1) / 2 - (x - 1 - x / 2)) / 2;}}int main() {init();while (scanf("%lld", &n) == 1 && n >= 3) {printf("%lld\n", s[n]);}return 0;}