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\),可以发现每个块对答案的贡献为:

\[\sum_{i = 1} ^ k \sum_{j = i + 1} ^ k (s_i + s_j) \times (n_i + n_j) \]

其中\(s_i\)表示这个集合中第\(i\)个块的格子编号,\(n_i\)表示其格子上的数字。

枚举一下\(k = 3\),发现原式为

\[s_1n_1 + s_1n_2 + s_2n_1 + s_2n_2 + s_1n_1 + s_1n_3 + s_3n_1 + s_3n_3 + s_2n_2 + s_2n_3 + s_3n_2 + s_3n_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)\)

把它展开,然后就等于

\[\sum_{i = 1} ^ k (k - 2)s_in_i + s_i \times \left( \sum \limits_{j = 1} ^ k n_j \right) \]

为了简便一点,设\(G = \sum \limits_{j = 1} ^ k n_j\)

那么就是

\[\sum_{i = 1} ^ k (k - 2)s_in_i + G\sum_{i = 1} ^ k s_i \\ = (k - 2) \sum_{i = 1} ^ k s_in_i + G\sum_{i = 1} ^ k s_i\\ \]

前缀和处理一下即可,别忘了取模。

时间复杂度应该是\(\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;
}
posted @ 2020-10-06 11:41  luyiming123  阅读(112)  评论(1编辑  收藏  举报