G. Hits Different
time limit per test | 2.5 seconds |
memory limit per test | 256 megabytes |
input | standard input |
output | standard output |
In a carnival game, there is a huge pyramid of cans with 2023 rows, numbered in a regular pattern as shown.
If can 9² is hit initially, then all cans colored red in the picture above would fall.
You throw a ball at the pyramid, and it hits a single can with number n². This causes all cans that are stacked on top of this can to fall (that is, can n² falls, then the cans directly above n² fall, then the cans directly above those cans, and so on). For example, the picture above shows the cans that would fall if can 9² is hit.
What is the sum of the numbers on all cans that fall? Recall that n² = n×n.
input
The first line contains an integer t (1≤t≤1000) ─ the number of test cases.
The only line of each test case contains a single integer n (1≤n≤10⁶) ─ it means that the can you hit has label n².
output
For each test case, output a single integer ─ the sum of the numbers on all cans that fall.
Please note, that the answer for some test cases won't fit into 32-bit integer type, so you should use at least 64-bit integer type in your programming language (like long long for c++). For all valid inputs, the answer will always fit into 64-bit integer type.
Example
input |
---|
10 |
9 |
1 |
2 |
3 |
4 |
5 |
6 |
10 |
1434 |
1000000 |
output |
156 |
1 |
5 |
10 |
21 |
39 |
46 |
146 |
63145186 |
58116199242129511 |
Note
The first test case is pictured in the statement. The sum of the numbers that fall is
1² + 2² + 3² + 5² + 6² + 9² = 1 + 4 + 9 + 25 + 36 + 81 = 156.
In the second test case, only the can labeled 1² falls, so the answer is 1² = 1.
In the third test case, the cans labeled 1² and 2² fall, so the answer is 1² + 2² = 1 + 4 = 5.
In the fourth test case, the cans labeled 1² and 3² fall, so the answer is 1² + 3² = 1 + 9 = 10.
In the fifth test case, the cans labeled 1², 2², and 4² fall, so the answer is 1² + 2² + 4² = 1 + 4 + 16 = 21.
————————————————————————————————————————————————————————————
题目大意就是指有一堆罐子从1到n²排成一座三角形垛,击中其中一个罐子,上面相关的罐子也会一起掉下来,仔细观察就会发现其实是以击中的罐子为顶点的半个倒三角形垛。
首先是构造图中的三角形垛:
long long can[1450][1450];
int i, j;
long long k = 1;
for(i=1;i<1450;i++){
for(j=1;j<=i;j++){
can[i][j] = k*k;
k++;
}
}
接着找规律:
1 ** ** ** **
2² 3² ** ** **
4² 5² 6² ** **
7² 8² 9² 10² **
11² 12² 13² 14² 15²
通过观察红色部分发现这就是半个倒三角垛,需要注意的是不要越界访问数组,于是要控制数组的边界范围。我们需要做的就是找到元素所在的位置,即精准定位被击中的罐子位于第几行第几个。本蒟蒻先使用连续自然数求和公式求出罐子所在的行,再用n减去前一行最后一个数定位罐子具体位置。n = 1 时直接输出1。求罐子所在行列代码如下:
long long k;
for(k=1;k<1450;k++){
if(k*(k+1)/2<n&&n<=(k+1)*(k+2)/2){
int m = n - k*(k+1)/2;//m表示被击中罐子所在的列
k++;//k表示被击中罐子所在的行
break;
}
}
一切就绪,开始求倒下罐子的sum值,部分代码如下:
long long sum = 0;
//k为被击中罐子所在行,m为被击中罐子所在列
for(i=0;i<k;i++){
for(j=0;j<=i&&m-j>0;j++){
sum += can[k-i][m-j];
}
}
最后将所有程序块组合,完成最终代码:
#include<stdio.h>
long long can[1450][1450];
int main(){
int i, j, m;
long long k = 1;
for(i=1;i<1450;i++){
for(j=1;j<=i;j++){
can[i][j] = k*k;
k++;
}
}//构造三角垛,即按顺序堆叠摆放好的罐子
int t;
scanf("%d", &t);
while(t--){
int n;
scanf("%d", &n);
if(n==1){
printf("1\n");
continue;
}//n为1直接输出1继续下一组
for(k=1;k<1450;k++){
if(k*(k+1)/2<n&&n<=(k+1)*(k+2)/2){
m = n - k*(k+1)/2;//确定被击中罐子的列
k++;//确定被击中罐子的行
break;
}//确定了罐子的位置后直接退出循环
}
long long sum = 0;
for(i=0;i<k;i++){
for(j=0;j<=i&&m-j>0;j++){
sum += can[k-i][m-j];
}//i表示当前行距离被击中罐子所在行的距离,j表示当前列距离罐子所在列的距离
}
printf("lld\n", sum);
}
return 0;
}
感谢看到这里,希望能给你带来帮助。(鞠躬)