• 【题解-SP1724 TRICOUNT】简单易懂的递推式写法


    原题:
    给你一个数N,下面是N行数据,每行一个数level,表示三角形的层数,对于每一个level,你需要输出其中三角形的个数。

    样例输入:

    3

    1

    2

    3

    样例输出:

    1

    5

    13

    数据范围:0<N<1000000,0<level<1000000。

    这道题其实用通项公式就可以A了,挺简单的...~~(奈何本蒟蒻不会)~~
    于是经过一番捣鼓,我还是得到了一个解法。(就类似于递推公式)
    关于通项公式的解法,非常简单:

    当level为偶数时,三角形个数为 level*(level+2)*(2*level+1)/8;

    当level为奇数时,三角形个数为 (level+1)*(2*level*level+3*level-1)/8。

    于是代码如下:

     1 #include<bits/stdc++.h>
     2 #define ull unsigned long long
     3 using namespace std;
     4 ull n,level;
     5 int main() 
     6 {
     7     cin>>n;
     8     for(ull i=1;i<=n;i++)
     9     {
    10         cin>>level;
    11         if(level%2)cout<<(level+1)*(2*level*level+3*level-1)/8<<endl;
    12         else cout<<level*(level+2)*(2*level+1)/8<<endl;
    13     }
    14 }

    但我不知道这个通项公式,也没那么多时间证,怎么办呢?

    对于level n而言,每增加至level n+1,那么新的三角形中包含的总三角形个数就等于:

    level n时总三角形个数 + level n+1时又新增的三角形个数。

    于是,我们只需要求出每增加一层后又新增的三角形数就完事了。

    (~~不过这个东西数起来好像有点脑阔疼。~~)

    我们可以分别数出新增加的正立三角形和倒立三角形的个数,这样子就比较好数,再把它们相加就可以了。

    撒,开始作业吧。

    ------------


    对于正三角形:
    level=1, 新增了边长为1的三角形1个。

    level=2,新增了边长为1的三角形2个,边长为2的三角形1个。

    level=3,新增了边长为1的三角形3个,边长为2的三角形2个,边长为3的三角形1个。

    level=4,新增了边长为1的三角形4个,边长为2的三角形3个,边长为3的三角形2个,边长为4的三角形1个。
    ……

    不难发现,设pz[i]为在增加至第i层时,较第i-1层应该新增的正三角形数的话,则pz[i]=pz[i-1]+i。

    再设z[i]为增加至第i层时总共的正三角形数,那么z[i]=z[i-1]+pz[i]。

    对于倒三角形:
    level=1, 新增了三角形0个。

    level=2,新增了边长为1的三角形1个

    level=3,新增了边长为1的三角形2个。

    level=4,新增了边长为1的三角形3个,边长为2的三角形1个。

    level=5,新增了边长为1的三角形4个,边长为2的三角形2个。

    level=6,新增了边长为1的三角形5个,边长为2的三角形3个,边长为3的三角形1个。

    level=7,新增了边长为1的三角形6个,边长为2的三角形4个,边长为3的三角形2个。

    level=8,新增了边长为1的三角形7个,边长为2的三角形5个,边长为3的三角形3个,边长为4的三角形1个。
     ……
    这么看可能不直观,我们把每一层新增的倒三角形数都加起来。

    level=1,新增0个。

    level=2,新增1个。

    level=3,新增2个。

    level=4,新增4个。

    level=5,新增6个。

    level=6,新增9个。

    level=7,新增12个。

    level=8,新增16个。


    直接说结论: 每当level为偶数时,新增倒三角形数较上一项新增倒三角形数的差都会+1。

    或者可以这样:对于每一level,在该level上新增倒三角形数较上一项上的差=floor((double)level/2)。(floor()是对一个数向下取整)。

    所以可以设pd[i]为在增加至第i层时,较第i-1层应该新增的倒三角形数,则pd[i]=pd[i-1]+floor((double)i/2)。

    再设d[i]为增加至第i层时总共的倒三角形数,那么d[i]=d[i-1]+pd[i]。

    至此,整个算法就明了了。
    不过时间复杂度上有些高,我们可以开个简单的记忆化,定义一个maxx,为目前到达过的最大层数,每次向后递推,总从第maxx层开始,当level<maxx时,直接输出z[level]+d[level]。
    最后是上代码~
    另外这道题在原Oj里要求代码长度小于500b,如果一直不过的话可以考虑一下这方面因素。

     1 #include<bits/stdc++.h>
     2 #define ull unsigned long long
     3 using namespace std;
     4 ull n,maxx=1,pz[50000005],pd[50000005],z[50000005],d[50000005];
     5 ull doit(int k)
     6 {
     7 if(k<=maxx) return z[k]+d[k];
     8 else{for(int i=maxx;i<=k;i++){
     9 pz[i]=pz[i-1]+i;
    10 z[i]=z[i-1]+pz[i];
    11 pd[i]=pd[i-1]+floor((double)i/2);
    12 d[i]=d[i-1]+pd[i];
    13 }
    14 return z[k]+d[k];
    15 }
    16 }
    17 int main()
    18 {
    19 cin>>n;
    20 int level;
    21 z[1]=1;
    22 for(int i=1;i<=n;i++){
    23 cin>>level;
    24 cout<<doit(level)<<endl;
    25 if(level>maxx) maxx=level;
    26 }
    27 }
  • 相关阅读:
    Django学习笔记(进阶篇)
    Django学习笔记(基础篇)
    vim的使用
    PyCharm默认文件头部的设置
    Django的内置登录、退出、修改密码方法
    vbox manjaro 无法挂载共享文件 解决办法
    vbox虚拟机 无法启动 新任务
    Ubuntu安装输入法
    安装 protobuf
    Manjaro.常用命令
  • 原文地址:https://www.cnblogs.com/MagicConchh/p/13535954.html
Copyright © 2020-2023  润新知