Codeforces Round 871(Div. 4) 1829G Hits Different

                                                                                        G. Hits Different

time limit per test2.5 seconds
memory limit per test256 megabytes
inputstandard input
outputstandard output

In a carnival game, there is a huge pyramid of cans with 2023 rows, numbered in a regular pattern as shown.

9a489958670d47898de8e84042c81116.png

                                         If can 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 . This causes all cans that are stacked on top of this can to fall (that is, can  falls, then the cans directly above  fall, then the cans directly above those cans, and so on). For example, the picture above shows the cans that would fall if can  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 (1t1000) ─ the number of test cases.

The only line of each test case contains a single integer (1n10⁶) ─ it means that the can you hit has label .

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 + 4 + 9 + 25 + 36 + 81 = 156.

In the second test case, only the can labeled 1² falls, so the answer is 1.

In the third test case, the cans labeled  and  fall, so the answer is + = 1 + 4 = 5.

In the fourth test case, the cans labeled and fall, so the answer is + = 1 + 9 = 10.

In the fifth test case, the cans labeled , , and fall, so the answer is + + = 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;
}

感谢看到这里,希望能给你带来帮助。(鞠躬)

  • 5
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值