• UVA 11401 Triangle Counting


    【题意分析】

    本题就是在给定的N条边(边长是1,2,3,,,N)里面找合乎要求的三角形个数(任意两条边之和大于第三边)。如果我们直接枚举合乎题意的三角形那么我们不太好出发(想想为什么?),那么我们可以采用补集观念,先找出不合乎要求的三角形数目,再用总的组合数减去不合乎要求的数目,就得最后的结果。那么问题是我们如何枚举不合乎要求的三角形数目呢?我们设三角形的三条边是a,b,c。我们不妨用c表示任意三条边中的边长最大值,那么我们可以得到一个简单的结论:如果能够构成三角形c<a+b.那么当用a和b作为边时,不符合要求的种数为:N-(a+b)+1(此时c>=a+b)。我们不妨令i=a+b。那么对于每一个i,a与b的组合方式有(i-1)/2种方式(仔细想想可以枚举一下有规律)。那么我们可以得到不符要求的组合方式有:(N-(i)+1)*((i-1)/2)种(3<=i<=N).考虑到本题的N可能很大,我们必须用long  long 存储数据。如果直接按照得到的公式从3到N进行相加,那么一定会超时。我们可以通过数学化简的形式简化计算过程使得算法的时间为O(1)。那么如何解决呢?

    我们需要考虑i为奇偶数的情况:

    当i为奇数(i=2*k+1)时(1<=k<=(N-1)/2),我们可以公式1计算:

     N * sum(n) - 2 * sum2(n);

    当i为偶数时(i=2*k+2)时(1<=k<N/2),我们可以采用公式2计算(这里有变换技巧注意体会):

    (N + 3) * sum(n) - 2 * sum2(n) - (LL)(N + 1) * n;

    其中:

    typedef long long LL;
    int N;
    LL sum(int n)
    {
        return (LL)n * (n + 1) / 2;
    }
    LL sum2(int n)
    {
        return (LL) n * (n + 1) * (2 * n + 1) / 6;
    }

    到这里我们用CN3 减去不符合要求的就行了。

    【AC代码】

    #include<stdio.h>
    #include<string.h>
    typedef long long LL;
    int N;
    LL sum(int n)
    {
        return (LL)n * (n + 1) / 2;
    }
    LL sum2(int n)
    {
        return (LL) n * (n + 1) * (2 * n + 1) / 6;
    }
    int main()
    {
        while(scanf("%d", &N), N >= 3)
        {
            LL ans = (LL)N * (N - 1) * (N - 2) / 6;
            int n = N / 2;
            ans -= (N + 3) * sum(n) - 2 * sum2(n) - (LL)(N + 1) * n;
            n = (N - 1) / 2;
            ans -= N * sum(n) - 2 * sum2(n);
            printf("%lld
    ", ans);
        }
        return 0;
    }
  • 相关阅读:
    获取指定目录下的所有文件
    char码值对应列表大全
    烂记性不如好笔头㈠㈢㈥
    SQL Server中的Image数据类型的操作
    企业信息化与标准化的纠结(二)
    企业信息化的前世今生
    企业信息化与标准化的纠结(一)
    关于 EOM(Enterprise Operating Model)企业经营模型(1) 转自n216
    《优秀程序员应该具备哪些素质》(ZT)
    谈谈MIS建设与职能架构的问题
  • 原文地址:https://www.cnblogs.com/khbcsu/p/4122287.html
Copyright © 2020-2023  润新知