P2671 [NOIP2015 普及组] 求和
前缀和
由题意可知
$y-x=z-y$
$z+x=2y$
故x,z的下标只可能同为奇数或同为偶数
接下来的操作默认奇偶位分开处理
$(x+z)*(number_x+number_z)=x*number_x+z*number_z+x*number_z+z*number_x$
对于奇或偶位所有某颜色的格子(设共$n$个),
答案$+=\sum i*\sum number_i-\sum i*number_i+(n-1)*\sum i*number_i$
对于一种颜色,我们用$s,x,p,q$数组分别储存 $number_i,i,number_i*i,$的和与某颜色格子的总数
答案$+=s*x+(q-2)*p$
#include<iostream> #include<cstdio> #include<cstring> using namespace std; const int N=100005; const int P=10007; int n,m,a[N],b[N],s[2][N],x[2][N],p[2][N],q[2][N],t; int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=n;++i) scanf("%d",&a[i]); for(int i=1;i<=n;++i) scanf("%d",&b[i]); for(int u=0;u<2;++u) for(int i=u+1;i<=n;i+=2){ s[u][b[i]]=(s[u][b[i]]+a[i])%P; x[u][b[i]]=(x[u][b[i]]+i)%P; p[u][b[i]]=(p[u][b[i]]+1ll*a[i]*i%P)%P; ++q[u][b[i]]; } for(int u=0;u<2;++u) for(int i=1;i<=m;++i){ t=(t+s[u][i]*x[u][i])%P; t=(t+1ll*(q[u][i]-2)*p[u][i]%P)%P; } printf("%d",t); return 0; }