[ABC384F] Double Sum 2 题解
F - Double Sum 2
中文题意
时空限制
时间限制:\(4\) 秒
空间限制:\(1024 \sf MB\)
题意描述
对于正整数 \(x\),按如下方式定义 \(f(x)\):“当 \(x\) 为偶数时,持续用 \(2\) 来除 \(x\)。经过这些除法运算后 \(x\) 的最终值就是 \(f(x)\)。” 例如,\(f(4) = f(2) = f(1) = 1\),以及 \(f(12) = f(6) = f(3) = 3\)。
给定一个长度为 \(N\) 的整数序列 \(A = (A_1, A_2, \dots , A_N)\),求 \(\sum_{i = 1}^{N} \sum_{j = i}^{N} f(A_i + A_j)\)
数据范围
-
\(1 \leq N \leq 2 \times 10^5\)
-
\(1 \leq A_i \leq 10^7\)
-
所有输入的值都是整数。
输入格式
\(N\)
\(A_1\) \(A_2\) \(\dots\) \(A_N\)
输入格式
输出答案。
样例#1解释
\(f(A_1+A_1)=f(8)=1,f(A_1+A_2)=f(12)=3,f(A_2+A_2)=f(16)=1\)。因此,输出 \(1+3+1=5\)。
解题
首先推式子.
令 \(S = 2^k \ (k \isin Z^*)\).
令 \(ans\) 初值为 \(\sum_{i=1}^{N} A_i \times (n + 1)\).
从 \(1\) 开始枚举 \(k\) 直到 \(S \gt 2 \times 10^7\).
对于每个 \(S\) 重新统计一遍 \(A_i + A_j \ (i \leqslant j)\) 能被 \(S\) 整除的值,并从 \(ans\) 中删去,具体操作见下.
从 \(1\) 到 \(n\) 枚举 \(i\),记录每一个 \(A_i\) 除以 \(S\) 的商、余数. 利用此前统计的数据,寻找和 \(A_i\) 的余数能凑成 \(S\) 或 \(0\) 的 \(A\) 值,并计算应得的和,减去.
注意:直接枚举找 \(A\) 时超时的,应开两个桶,记录之前数的商、余数.
最后对每个 \(S\) 清空桶.
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <cassert>
using namespace std;
const int NR = 1e5 + 10;
const int SR = 2e7 + 10;
long long a[NR];
long long bp[SR], bq[SR];
int main()
{
int n;
scanf("%d", &n);
long long ans = 0;
for (int i = 1; i <= n; i ++)
{
scanf("%lld", &a[i]);
ans += a[i] * (n + 1);
}
for (long long S = 2; S <= 2e7; S *= 2)
{
for (int i = 1; i <= n; i ++)
{
long long p = a[i] / S, q = a[i] % S;
bp[q] += p;
bq[q] ++;
if (q == 0)
{
ans -= bp[0] + p * bq[0];
}
else
{
ans -= bp[S - q] + (p + 1) * bq[S - q];
}
}
for (int i = 1; i <= n; i ++)
{
long long p = a[i] / S, q = a[i] % S;
bp[q] -= p;
bq[q] --;
}
}
printf("%lld\n", ans);
return 0;
}
对代码 \(31\) ~ \(38\) 行的说明: 对于这个 \(A_i = p \times S + q\) 的 \(A_i\),我们要寻找余数为 \(S - q\) 、位置 \(\leqslant i\) 的 \(A\) 值. bp[S - q] 储存了余数为 \(S - q\) 所有数除以 \(S\) 的商的和,bq[S - q] 储存了余数为 \(S - q\) 的数的总数量. 本次对 \(ans\) 的负贡献首先是 bp[S - q];其次对 bq[S - q] 中的每一个,有一个的 \(A_i\) 的商做贡献,还有 \(\frac{q + (S - q)}{S}=1\) 的贡献,对 \(q = 0\) 另当别论. 于是普通情况中 ans -= bp[S - q] + (p + 1) * bq[S - q];,易得 \(q = 0\) 时 ans -= bp[0] + p * bq[0];.

浙公网安备 33010602011771号