原题:
给你一个数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 }