题解 CF1829G Hits Different
cjh20090318 · · 题解
大家好,我是 CQ-C2024 蒟蒻 CJH。
题意
本题有多组数据。
有一个高
你击中了一个编号为
分析
设
所以可以很容易地发现几点:
- 该罐子编号为
1 ,不存在左上方和右上方。 - 第
x 层最左侧罐子的r_{\frac{x(x+1)}{2}-x+1}=\dfrac{x(x-1)}{2}-x+2 ,不存在左上方。 - 第
x 层最右侧罐子的l_{\frac{x(x+1)}{2}}=\dfrac{x(x-1)}{2} ,不存在右上方。 - 其余罐子
i 的l_i=r_{i-1} ,r_i=l_i+1 。
经过观察
然后预处理
总体时间复杂度 竟然成为最优解!
注意事项
注意 long long 存储。
代码
//the code is from chenjh
#include<cstdio>
#define MAXN 1000001
typedef long long LL;
int l[MAXN],r[MAXN];//左上方和右上方。
LL f[MAXN];//答案数组。
void solve(){
int n;scanf("%d",&n);
printf("%lld\n",f[n]);
}
int main(){
for(int i=2;(((LL)i*(i+1))>>1ll)<MAXN+i-1;i++)r[((i*(i+1))>>1)-i+1]=((i*(i-1))>>1)-i+2;//预处理第二点。
for(int i=2;(((LL)i*(i+1))>>1ll)<MAXN;i++)l[(i*(i+1))>>1]=(i*(i-1))>>1;//预处理第三点。
for(int i=2;i<MAXN;i++){
if(l[i]||r[i]) continue;//如果左上方或右上方编号已经处理过,说明是边界节点,直接跳出即可。
l[i]=r[i-1],r[i]=l[i]+1;//预处理第四点。
}
f[1]=1;//记得赋初值!
for(int i=2;i<MAXN;i++) f[i]=f[l[i]]+f[r[i]]-f[l[r[i]]]+(LL)i*i;//预处理 f 数组。
int T;scanf("%d",&T);
while(T--) solve();
return 0;
}