[前缀和]P2671 [NOIP 2015 普及组] 求和 题解

朴素的前缀和优化题

P2671

阅读题面,发现在题目中 \(x , y , z\) 的三元组中 \(y\) 没有用,相当于是任意两个下标同奇偶的 \(x , z\) 进行操作。

把式子拆一下

\[(x + z) \times (num_x + num_z) \]

\[= x \times num_x + z \times num_x + x \times num_z + z \times num_z \]

然后发现这些东西全部可以预处理。把含 \(x\) 的项分离出来之后,分四个数组分奇偶从后往前做前缀和就行。

#include <bits/stdc++.h>
#define int long long
constexpr int N = 1e5 + 5;
constexpr int mod = 10007;
using namespace std;
int ans , n , m , num[N] , colour[N] , sum1[N][2] , sum2[N][2] , sum3[N][2] , sum4[N][2];
signed main() {
	cin >> n >> m;
	for(register int i = 1; i <= n; ++i) {
		cin >> num[i];
	}
	for(register int i = 1; i <= n;++i) {
		cin >> colour[i];
	}
	for(register int i = n; i; --i) {
		ans = (ans + (i * num[i] * sum1[colour[i]][i & 1] + num[i] * sum2[colour[i]][i & 1] + i * sum3[colour[i]][i & 1] + sum4[colour[i]][i & 1]) % mod) % mod;
		sum1[colour[i]][i & 1] ++;
		sum2[colour[i]][i & 1] += i;
		sum3[colour[i]][i & 1] += num[i];
		sum4[colour[i]][i & 1] += i * num[i];
	}
	cout << ans;
	return 0;
}
posted @ 2025-06-27 20:54  風月華  阅读(14)  评论(0)    收藏  举报