关闭

UVa 11401 Triangle Counting

标签: 组合数学
138人阅读 评论(0) 收藏 举报
分类:


来源:《算法竞赛训练指南》例题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

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:9656次
    • 积分:572
    • 等级:
    • 排名:千里之外
    • 原创:51篇
    • 转载:0篇
    • 译文:0篇
    • 评论:0条
    文章分类