P2671 求和
这题其实是有一点心理阴影的,很久以前不知道为啥,\(O(n^2)\)的暴力没有打对,过了这么久,今天莽一个正解,写了1张A4纸,通过不懈努力,还是AC了。
部分分:
\(\mathcal{O}(n^3)\) 枚举\(x,y,z\),进行求和,注意取模!!!
\(\mathcal{O}(n^2)\) 发现这个\(y - x = z - y\)很屑,直接转换成\(x + z = 2y\),后面发现这个\(y\)一点用没有,所以前面的式子可以理解为\(x + z\)为偶数。枚举\(x,z\)。
正解:
要使\(x + z\)为偶数,那么\(x,z\)奇偶必定相同,也就是\(x = z \pmod{2}\),还有一个\(color_x = color_z\),将其分组,\(Q[col][x]\)表示颜色为\(col\),除以2的余数为\(x\)的方块集合。通过令其长度为\(k\),可以发现每个块对答案的贡献为:
其中\(s_i\)表示这个集合中第\(i\)个块的格子编号,\(n_i\)表示其格子上的数字。
枚举一下\(k = 3\),发现原式为
将带有\(s_1\)的式子提出:\(s_1n_1 + s_1n_2 + s_1n_1 + s_1n_3\)
将带有\(s_2\)的式子提出:\(s_2n_1 + s_2n_2 + s_2n_2 + s_2n_3\)
不难归纳出含有\(s_i\)的式子的贡献\(= (k - 2)s_in_i + s_2 \times \left(\sum \limits_{j = 1} ^ k n_j \right)\)
设上面那坨式子为\(Q(i)\),那么一个块的贡献就是\(\sum \limits_{i = 1} ^ k Q(i)\)
把它展开,然后就等于
为了简便一点,设\(G = \sum \limits_{j = 1} ^ k n_j\)
那么就是
前缀和处理一下即可,别忘了取模。
时间复杂度应该是\(\mathcal{O}(m)\)的
#include <bits/stdc++.h>
using namespace std;
const int N = 100004;
int n, m;
long long Q1[N][2], Q2[N][2], Q3[N][2], siz[N][2];
long long num[N], col[N];
const int mod = 10007;
long long ans = 0;
void solve(void)
{
for (int i = 1; i <= m; i++)
{
for (int j = 0; j <= 1; j++)
{
// printf("Q1[%d][%d] = %d,Q2[%d][%d] = %d,Q3[%d][%d] = %d,siz[%d][%d] = %d\n", i, j, Q1[i][j], i, j, Q2[i][j], i, j, Q3[i][j], i, j, siz[i][j]);
ans = (ans + ((siz[i][j] - 2) % mod * (Q1[i][j]) % mod) % mod + (Q2[i][j] % mod * Q3[i][j] % mod) % mod);
}
}
return;
}
int main(void)
{
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++)
{
scanf("%lld", &num[i]);
}
for (int i = 1; i <= n; i++)
{
scanf("%lld", &col[i]);
}
for (int i = 1; i <= n; i++)
{
Q1[col[i]][i % 2] = (Q1[col[i]][i % 2] + (i * num[i]) % mod) % mod;
Q2[col[i]][i % 2] = (Q2[col[i]][i % 2] + num[i]) % mod;
Q3[col[i]][i % 2] = (Q3[col[i]][i % 2] + i) % mod;
siz[col[i]][i % 2]++;
// printf("col[i] = %d,i % 2 = %d,Q1[col[i]][i % 2] = %d\n", col[i], i % 2, Q1[col[i]][i % 2]);
}
solve();
printf("%lld\n", ans % mod);
return 0;
}