P2671 [NOIP2015 普及组] 求和

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;
}

 

posted @ 2021-07-11 13:16  kafuuchino  阅读(65)  评论(0编辑  收藏  举报