zoukankan      html  css  js  c++  java
  • 洛谷

    https://www.luogu.org/problemnew/show/P2181

    对于某条对角线,除去从两端出发的对角线,其他的都与它有1个交点。

    每个点有(n-3)条对角线,每条对角线和其余C(n-2,2)条对角线都有1个交点,共有n个点,重复计算交点再除以2,重复计算直线再除以2。

    即n(n-3)/2条对角线,每条对角线和(n-2)(n-3)/2条对角线都有1个交点,重复计算交点再除以2。(错了,并非所有对角线都相交


    画图手数,按规律数的话,发现n=4,1个交点;n=5,5个交点=sum(1,2)+2sum(1,1);n=6,15个交点=sum(1,3)+2sum(1,2)+3sum(1,1);n=7,35个交点=sum(1,4)+2sum(1,3)+3sum(1,2)+4sum(1,1)。

    所以我们首先得到一个n复杂度的解法。利用这个解法打表看看。

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    
    ll sum(ll a1,ll an){
        return (an-a1+1)*(a1+an)/2;
    }
    
    int main(){
        for(int n=3;n<=20;n++){
            ll ans=0;
            for(int i=1;i<=n-3;i++){
                ans+=1ll*i*sum(1,n-2-i);
            }
            printf("n=%d  ans=%lld
    ",n,ans);
        }
    
    }
    n=3  ans=0
    n=4  ans=1
    n=5  ans=5
    n=6  ans=15
    n=7  ans=35
    n=8  ans=70
    n=9  ans=126
    n=10  ans=210
    n=11  ans=330
    n=12  ans=495
    n=13  ans=715
    n=14  ans=1001
    n=15  ans=1365
    n=16  ans=1820
    n=17  ans=2380
    n=18  ans=3060
    n=19  ans=3876
    n=20  ans=4845

    再试试大点的会不会爆,结果看不太出来,用ull和ll的结果没啥不同,赌他不溢出。

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    
    unsigned ll sum(ll a1,ll an){
        return (an-a1+1)*(a1+an)/2;
    }
    
    int main(){
        int n;
        scanf("%d",&n);
        //for(int n=99999;n<=100000;n++){
            unsigned ll ans=0;
            for(int i=1;i<=n-3;i++){
                ans+=1llu*i*sum(1,n-2-i);
            }
            //printf("n=%d  ans=%llu
    ",n,ans);
            printf("%llu
    ",ans);
        //}
    
    }

    事实证明是没有溢出。所以上面是正确的解法。

    这道题还有用公式的解法,降低了一个维度。除了用组合数学的知识直接得到(4个不同的点确定一个交点,直接C(n,4)),还可以暴力求解,这里介绍一下高阶差分。

    首先我们由打表代码得到

    0 1 5 15 35 70 126

    一阶差分

    1 4 10 20 35 56

    二阶差分

    3 6 10 15 21

    三阶差分

    3 4 5 6

    四阶差分

    1 1 1

    五阶差分

    0 0

    所以上式是一个关于n的四次多项式。设为an^4+bn^3+cn^2+dn+e=0。

    代入前5项强行算出来吧。还是说有别的计算方法?

    的确有!(差分数列只要得到等差数列即可)

    写出差分表之后,差分表的每行第0项组成第0对角线,即c0,c1,c2,c3,0,0,0...。原序列的通项满足

    hn=c0C(n,0)+c1C(n,1)+c2C(n,2)+c3C(n,3),利用这个形式甚至可以求出前n项和。(组合数的求和sum(k=0~n,C(k,p))=C(k+1,p+1))


    参考https://blog.csdn.net/wu_tongtong/article/details/79115921

  • 相关阅读:
    【poj 1087 a plug for UNIX】
    收集 数据库的awr数据,生成报告
    power desinger 学习笔记三<批量执行sql语句>
    power desinger 学习笔记<二>
    power desinger 学习笔记<一>
    oracle中不曾熟悉的 to_char、to_number(未完待续)
    oracle 报错 :ORA-04052、 ORA-00604、 ORA-03106、 ORA-02063
    谈谈oracle中的临时表
    Oracle-在线重定义操作文档
    分享最近和同事处理的 解析XML的相关问题
  • 原文地址:https://www.cnblogs.com/Yinku/p/10328616.html
Copyright © 2011-2022 走看看