UVa 11401 Triangle Counting

来源:互联网 发布:诺基亚n8软件专区 编辑:程序博客网 时间:2024/05/16 07:27


来源:《算法竞赛训练指南》例题2-2、UVa 11401
题目描述:
求从1…n中选出三个【不同】的数作为三角形合法三条边的方案数。
题目分析:
假设选出来的三个合法的数是p、q、r,则有p + q > r现在要求p < q < r,下面做一点分析。
考虑q = r - 1,则p取值空间为[2, r - 2],一共有r - 3个数。
考虑q = r - 2,则p取之空间为[3, r - 3],一共有r - 5个数。
归纳法或者画画图就知道p的取值方案数是一个等差数列,首项是r - 3,考虑实际意义末项当r为奇数时为0,偶数时为1。记最长边为r(r > 3)时共有g(r)种可行方案,则

g(r)=r/21+(r1)/2
如果不好理解也可以奇偶讨论。实际上注意到c++中整数除法是向零取整(对正数就是向下取整)即可得到公式的正确性。
依次令4…n为最长边,又有
g(1)=g(2)=g(3)=0
记题目所求方案数为f(n);就有
f(n)=i=1ng(i)
于是
f(n)=f(n1)+g(n)

由于我们在计数的时候确保了p < q < r,且 p + q > r 所以不会有重复计数或者不合法计数;由于r是递增的且我们遍历了所有可能的q,所以这样的计数是没有遗漏的。
具体实现时小心递推时 i 是long long型以防溢出。算法耗时主要在对数组的递推,这个时间关于n是线性的。

//  Created by wander on 16/6/1.//  Copyright © 2016年 W4anD0eR96. All rights reserved.//  UVa 11401 Triangle Counting//  类型:组合数学#include "bits/stdc++.h"using namespace std;unsigned long long f[1000050];int n;int main() {#ifdef DEBUG  freopen("in", "r", stdin);  freopen("out", "w", stdout);#endif  // pre-process  for (unsigned long long i = 4; i < 1000050; i += 1)    f[i] = f[i - 1] + ((i >> 1) - 1) * ((i - 1) / 2);  // input and work  while (~scanf("%d", &n) && n >= 3)    printf("%llu\n", f[n]);  return 0;}
0 0
原创粉丝点击