P2671 求和 题解
令
让我们来看看得分公式:
由乘法分配率可知:
我们设可以以
可得集合
整理可得:
我们把
再看题目要求:
这个分数可能会很大,你只要输出整个纸带的分数除以10,007所得的余数即可。
所以我们应该利用同余定理改写这个公式:
记住下面这个恒等式:
设
由题意得:
我们利用前缀和优化这个公式,可将时辅优化到
可能你对集合
特殊三元组
由题意得:
-
x<y<z -
z-y=y-x -
color_x=color_z
为了方便,我们设
则有:
那该三元组和y还有什么关系
所以我们只要满足
前缀和优化如下:
设
再设
一边输入颜色,就可一边累加,然后你就可以AC掉本题了。
完整代码如下:
#include <cstdio>
const int N = 100000;
const int M = 10007;
int n, m;
int sum[N + 1][2], nt[N + 1][2];
int color[N + 1], number[N + 1];
long long ans = 0;
int main()
{
scanf(" %d %d", &n, &m);
for(int i = 1; i <= n; i++) {
scanf("%d", &number[i]);
number[i] %= M;
}
for(int i = 1; i <= n; i++) {
scanf("%d", &color[i]);
int c = color[i];
int g = i % 2;
nt[c][g]++;
sum[c][g] += number[i];
sum[c][g] %= M;
}
for(int i = 1; i <= n; i++) {
int c = color[i];
int g = i % 2;
ans += i % M * ((sum[c][g] + (nt[c][g] - 2) % M * number[i] + M) % M);
ans %= M;
}
printf("%lld", ans);
return 0;
}