G. Hits Different

Posted onlyblues

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了G. Hits Different相关的知识,希望对你有一定的参考价值。

G. Hits Different

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

If can $9^2$ 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^2$. This causes all cans that are stacked on top of this can to fall (that is, can $n^2$ falls, then the cans directly above $n^2$ 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^2$ is hit.

What is the sum of the numbers on all cans that fall? Recall that $n^2 = n \\times n$.

Input

The first line contains an integer $t$ ($1 \\leq t \\leq 1000$) — the number of test cases.

The only line of each test case contains a single integer $n$ ($1 \\leq n \\leq 10^6$) — it means that the can you hit has label $n^2$.

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 + 2^2 + 3^2 + 5^2 + 6^2 + 9^2 = 1 + 4 + 9 + 25 + 36 + 81 = 156.$$

In the second test case, only the can labeled $1^2$ falls, so the answer is $1^2=1$.

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

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

In the fifth test case, the cans labeled $1^2$, $2^2$, and $4^2$ fall, so the answer is $1^2+2^2+4^2=1+4+16=21$.

 

解题思路

  我们先对金字塔转换成矩阵的形式,结果如下图:

  以上图为例子,如果选择$13$号的格子,此时对应的坐标为$(5,3)$(矩阵坐标系)。那么在金字塔中的上一行与$13$号格子有接触的是$8$号和$9$号格子,因此我们想到能不能利用$8$号和$9$号格子的结果来得到$13$号格子的结果呢?

  定义$f(x)$表示从$x$号格子往上能走到的与其接触的格子的值之和。先给出结论,$f(13) = 13^2 + f(8) + f(9) - f(5)$。为什么要减去一个$f(5)$?这是因为从$8$号格子往上走会经过$4$号格子与$5$号格子,从$9$号格子往上走会经过$5$号格子与$6$号格子,因此$f(8)+f(9)$会有重复的部分,即$f(5)$,因此减去即可,有容斥原理的思想在里面。

  递推公式知道了,那么接下来问题是我知道了$x$号格子,怎么得到上面的两个格子的编号呢?在矩阵的表示中可以发现第$i$行恰好有$i$个格子,因此如果知道当前$x$号格子的坐标为$(i,j)$,那么上面两个的坐标就是$(i-1,j)$和$(i-1,j-1)$,要减去的格子坐标是$(i-2,j-1)$。而已知坐标推格子编号还是很容易的,有公式$g(i,j) = \\sum\\limits_k=1^i-1k+j = \\dfraci \\cdot (i-1)2+j$,因此递推公式就变成了$$f(g(i,j)) = g^2(i,j) + f(g(i-1,j)) + f(g(i-1,j-1)) - f(g(i-2,j-1))$$

  可以发现每次用到的都是上一行的结果,因此我们可以从第$2$行开始往下递推(其中$f(1)=1$)。然后可能往上走有些格子并不存在,此时公式就有所变化了,如果对应的格子不存在那么直接不考虑该项结果即可,对应的细节处理见代码。

  我们直接预处理出来$10^6$以内的$f(x)$,询问的时候直接查表,因此计算量为$O(10^6 + T)$。

  AC代码如下:

 #include <bits/stdc++.h>
 using namespace std;
 
 typedef long long LL;
 
 const int N = 1e6 + 10;
 
 LL f[N];
 
 void init() 
     f[1] = 1;   // 边界情况f(1)=1
     for (int i = 2, k = 2; k < N; i++)     // 从第2行开始枚举,k是要枚举的格子编号
         for (int j = 1; j <= i; j++, k++)  // 第i行最多有i列,即纵坐标不超过横坐标
             f[k] = 1ll * k * k;
             if (i - 1 > 0)     // 上一行(第i-1行)存在
                 if (j <= i - 1) f[k] += f[(i - 2) * (i - 1) / 2 + j];   // 列不超过行,存在格子(i-1,j)
                 if (j - 1 > 0)     // 首先必然有j-1 <= i-1,然后还要保证j-1 > 0,没有越界,才存在格子(i-1,j-1)
                     f[k] += f[(i - 2) * (i - 1) / 2 + j - 1];
                     if (i - 2 > 0 && j - 1 <= i - 2) f[k] -= f[(i - 3) * (i - 2) / 2 + j - 1];  // 第i-2行存在且列不超过行(已经保证j-1 > 0了)
                 
             
         
     
 
 
 void solve() 
     int n;
     scanf("%d", &n);
     printf("%lld\\n", f[n]);
 
 
 int main() 
     init();
     int t;
     scanf("%d", &t);
     while (t--) 
         solve();
     
     
     return 0;
 

 

参考资料

  Codeforces Round 871 (Div. 4) A - H:https://zhuanlan.zhihu.com/p/627396904

BigQuery(谷歌分析数据):在同一个“hits.hitNumber”中查询两个不同的“hits.customDimensions.index”

【中文标题】BigQuery(谷歌分析数据):在同一个“hits.hitNumber”中查询两个不同的“hits.customDimensions.index”【英文标题】:BigQuery (Google Analytics data):query two different 'hits.customDimensions.index' in the same 'hits.hitNumber' 【发布时间】:2020-01-09 16:55:22 【问题描述】:

我的目标:

如果以下两个 hits.customDimensions.index 和关联的 hits.customDimensions.value 出现在相同的 hits.hitNumber 中,则会话计数为 1(如果主查询仍然嵌套,则每行都是 1 个会话):

['hits.customDimensions.index' = 43 关联 'hits.customDimensions.value' IN ('login', 'payment', 'order', 'thankyou')] AND ['hits.customDimensions.index' = 10 关联 'hits.customDimensions.value' = 'checkout' [在同一个 hits.hitNumber]

我的问题

我不知道如何在没有不同 WITH 表的情况下在一个子查询中查询相同 hits.hitNumber 中的两个不同 hits.customDimensions.value。如果可能的话,我敢肯定,查询将非常简单和简短。因为我不知道如何在子查询中查询这个用例,所以我使用了一个总计为 5 个 WITH 表的解决方法。 我希望有一种查询此用例的简单方法

解释变通方法查询:

Table1:查询除“problem-metric”之外的所有内容

表 2-3:每个表查询一个 hits.customDimensions.index,关联的 hits.customDimensions.value 过滤为正确的值,sessionId 和 hitNumber

table4:根据日期、sessionID 和 hitNumber 将表 2 与表 3 左连接。基本上,如果 hitNumber 与 table2 和 table3 中的 sessionId 相结合,我算 1

table5:left join table1和table4来合并数据

#Table1 - complete data except session_atleast_loginCheckout
WITH
  prepared_data AS (
  SELECT
    date,
    SUM((SELECT 1 FROM UNNEST(hits) WHERE CAST(eCommerceAction.action_type AS INT64) BETWEEN 4 AND 6 LIMIT 1)) AS sessions_atleast_basket, 
    #insert in this row query for sessions_atleast_loginCheckout
    SUM((SELECT 1 FROM UNNEST(hits) as h, UNNEST(h.customDimensions) as hcd WHERE index = 43 AND value IN ('payment', 'order', 'thankyou') LIMIT 1)) AS sessions_atleast_payment,
  FROM
    `big-query-221916.172008714.ga_sessions_*`
  WHERE
    _TABLE_SUFFIX BETWEEN FORMAT_DATE('%Y%m%d',DATE_SUB(CURRENT_DATE(), INTERVAL 1 DAY)) AND FORMAT_DATE('%Y%m%d',DATE_SUB(CURRENT_DATE(), INTERVAL 1 DAY)) AND totals.visits = 1 
  GROUP BY
    date


#Table2 - data for hits.customDimensions.index = 10 AND associated hits.customDimensions.value = 'checkout' with hits.hitNumber and sessionId (join later based on hitNumber and sessionId)
loginCheckout_index10_pagetype_data AS (
  SELECT
    date AS date,
    CONCAT(fullVisitorId, '/', CAST( visitStartTime AS STRING)) AS sessionId,
    h.hitNumber AS hitNumber,
    IF(hcd.value IS NOT NULL, 1, NULL) AS pagetype_checkout
  FROM
    `big-query-221916.172008714.ga_sessions_*` AS o, UNNEST(hits) as h, UNNEST(h.customDimensions) as hcd
  WHERE
    _TABLE_SUFFIX BETWEEN FORMAT_DATE('%Y%m%d',DATE_SUB(CURRENT_DATE(), INTERVAL 1 DAY)) AND FORMAT_DATE('%Y%m%d',DATE_SUB(CURRENT_DATE(), INTERVAL 1 DAY)) AND hcd.index = 10 AND VALUE = 'checkout'  AND h.type = 'PAGE' AND totals.visits = 1),


#Table3 - data for hits.customDimensions.index = 43 AND associated hits.customDimensions.value IN ('login', 'register', 'payment', 'order','thankyou') with hits.hitNumber and sessionId (join later based on hitNumber and sessionId)
loginCheckout_index43_pagelevel1_data AS (
  SELECT
    date AS date,
    CONCAT(fullVisitorId, '/', CAST( visitStartTime AS STRING)) AS sessionId,
    h.hitNumber AS hitNumber,
    IF(hcd.value IS NOT NULL, 1, NULL) AS pagelevel1_login_to_thankyou
  FROM
    `big-query-221916.172008714.ga_sessions_*` AS o, UNNEST(hits) as h, UNNEST(h.customDimensions) as hcd
  WHERE
    _TABLE_SUFFIX BETWEEN FORMAT_DATE('%Y%m%d',DATE_SUB(CURRENT_DATE(), INTERVAL 1 DAY)) AND FORMAT_DATE('%Y%m%d',DATE_SUB(CURRENT_DATE(), INTERVAL 1 DAY)) AND hcd.index = 43 AND VALUE IN ('login', 'register', 'payment', 'order', 'thankyou') AND h.type = 'PAGE'  
),


#table4 - left join table2 and table 3 on sessionId and hitNumber to get sessions_atleast_loginCheckout
loginChackout_output_data AS(
  SELECT
    a.date AS date,
    COUNT(DISTINCT a.sessionId) AS sessions_atleast_loginCheckout 
  FROM
    loginCheckout_index10_pagetype_data AS a
  LEFT JOIN 
    loginCheckout_index43_pagelevel1_data AS b 
  ON
    a.date = b.date AND
    a.sessionId = b.sessionId AND
    a.hitNumber = b.hitNumber
  WHERE
    pagelevel1_login_to_thankyou IS NOT NULL
  GROUP BY
    date



#table5 - leftjoin table1 with table4 to get all data together
SELECT
  prep.date,
  prep.sessions_atleast_basket,
  log.sessions_atleast_loginCheckout,
  prep.sessions_atleast_payment
FROM
    prepared_data AS prep
  LEFT JOIN
    loginChackout_output_data as log
  ON
    prep.date = log.date AND


【问题讨论】:

为什么要减少 CTE 的数量?在我看来,你在每一个中都封装了不同的逻辑,这将使你的队友(或 6 个月后的你)更容易阅读。新线路很便宜,脑力很贵。 为了安全起见,我目前一个人,经验不足。我也不确定是否有其他方法(可以理解和合乎逻辑)。 【参考方案1】:

这有点像《盗梦空间》,但记住unnest() 的输入是一个数组而输出是表格行可能会有所帮助...

SELECT
  SUM(totals.visits) as sessions
FROM
  `big-query-221916.172008714.ga_sessions_*`
WHERE
    _TABLE_SUFFIX BETWEEN FORMAT_DATE('%Y%m%d',DATE_SUB(CURRENT_DATE(), INTERVAL 1 DAY)) AND FORMAT_DATE('%Y%m%d',DATE_SUB(CURRENT_DATE(), INTERVAL 1 DAY)) 
  AND -- the following two hits.customDimensions.index and associated hits.customDimensions.value appear in the same hits.hitNumber
    (SELECT COUNT(1)>0 as hitsCountMoreThanZero FROM UNNEST(hits) AS h
     WHERE 
       -- index 43, value IN ('login', 'payment', 'order', 'thankyou')
       (select count(1)>0 from unnest(h.customdimensions) where index=43 and value IN ('login', 'payment', 'order', 'thankyou'))
       AND
       -- index 10, value = 'checkout'
       (select count(1)>0 from unnest(h.customdimensions) where index=10 and value='checkout')
    )
GROUP BY
  date

【讨论】:

以上是关于G. Hits Different的主要内容,如果未能解决你的问题,请参考以下文章

BigQuery(谷歌分析数据):在同一个“hits.hitNumber”中查询两个不同的“hits.customDimensions.index”

HITS

Google Analytics 和 BigQuery 之间的会话不匹配,同时将 hits 和 hits.product 取消嵌套

在 BigQuery 中使用“hits.column name”为未嵌套的匹配列添加前缀

链接分析算法之:HITS算法

搜索引擎算法研究专题六:HITS算法