• 【计数】【UVA11401】 Triangle Counting


    传送门

    Description

      把1……n这n个数中任取3个数,求能组成一个三角形的方案个数

    Input

      多组数据,对于每组数据,包括:

    • 一行一个数i,代表前i个数。

      输入结束标识为i<3.

    Output

      对于每组数据,输出:

    • 对应的方案个数

    Sample Input

    5
    8
    0

    Sample Output

    3
    22

    Hint

    n≤1e6。

    三个数字x,y,z能组成三角形当且仅当对于任意顺序,都满足x+y>z。

    Solution

      考虑把所有能组成的三角形按照最长边分类。因为三边长度互不相同,所以每个三角形都会被唯一的归为一类。设fi为最长边为i的方案个数,那么按照加法原理,n以内的方案个数=∑(i :3 to n)fi。考虑三角形三边关系定理,对于三遍x,y,z,不妨设x是最长边,那么满足y+z>x,移项得z>x-y。又因为x是最长边,故有x-y<z<x。

      考虑乘法原理,先确定y,当y=1时,无解;y=2时,有1个解。进行数学归纳易证y=x-1时,有x-2个解。根据等差数列的求和公式,解的个数为∑x-1i=1=(x-1)(x-2)/2。但是需要注意的是这样包括了y=z的情况。需要减掉。另外这样每个三角形被计算了两遍,需要除以二。

      对于y=z的情况被统计到,当且仅当y<x/2。所以需要减掉(x-1)/2。最后递推解决前n个的问题即可。

      需要注意的是开longlong

    Code

    #include<cstdio>
    #define rg register
    #define ci const int
    
    typedef long long int ll;
    
    namespace IO {
        char buf[50];
    } 
    
    inline void qr(int &x) {
        char ch=getchar(),lst=' ';
        while(ch>'9'||ch<'0') lst=ch,ch=getchar();
        while(ch>='0'&&ch<='9') x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
        if(lst=='-') x=-x;
    }
    
    inline void write(ll x,const char aft,const bool pt) {
        if(x<0) {putchar('-');x=-x;}
        int top=0;
        do {
            IO::buf[++top]=x%10+48;
            x/=10;
        } while(x);
        while(top) putchar(IO::buf[top--]);
        if(pt) putchar(aft);
    }
    
    template <typename T>
    inline T mmax(const T &a,const T &b) {if(a>b) return a;return b;}
    template <typename T>
    inline T mmin(const T &a,const T &b) {if(a<b) return a;return b;}
    template <typename T>
    inline T mabs(const T &a) {if(a>=0) return a;return -a;}
    
    template <typename T>
    inline void mswap(T &a,T &b) {T temp=a;a=b;b=temp;}
    
    const int maxn = 1000001;
    
    ll frog[maxn];
    int a;
    
    int main() {
        for(rg int i=4;i<maxn;++i) {
            frog[i]=frog[i-1]+(((1ll*(i-1)*(i-2)>>1)-((i-1)>>1))>>1);
        }
        a=0;qr(a);
        while(a>=3) {
            write(frog[a],'
    ',true);
            a=0;qr(a);
        }
        return 0;
    }

    Summary

    在统计时,及时去重是必要的。

    在lg的题解上有神仙找规律……反正我没法证明

    设fi为i个的ans,则fi=fi-2+i-3

  • 相关阅读:
    42、lucene和机器学习进行全文搜索,并排序
    41、javaMail机制
    40、dom以xml结尾的文件
    39、重新复习js之三
    38、重新复习javascript之三
    36、重新复习html和css之二
    35、重新复习html与css(1)
    34、Shiro框架入门三,角色管理
    33、插入一段大学学的计算机,正儿八经的计算机图形学
    32、shiro框架入门3.授权
  • 原文地址:https://www.cnblogs.com/yifusuyi/p/9465123.html
Copyright © 2020-2023  润新知