[Noip2015PJ] 求和

一条狭长的纸带被均匀划分出了 \(n\) 个格子,格子编号从 \(1\)\(n\) 。每个格子上都染了一种颜色 \(color_i\)\([1,m]\) 当中的一个整数表示),并且写了一个数字 \(number_i\)

img

定义一种特殊的三元组:\((x,y,z)\),其中 \(x,y,z\) 都代表纸带上格子的编号,这里的三元组要求满足以下两个条件:

\(x,y,z\) 是整数, \(x<y<z\)\(y-x=z-y\)

\(color_x=color_z\)

满足上述条件的三元组的分数规定为 \((x+z)\times (number_x+number_z)\)。整个纸带的分数规定为所有满足条件的三元组的分数的和。这个分数可能会很大,你只要输出整个纸带的分数除以 \(10,007\) 所得的余数即可。

Input

第一行是用一个空格隔开的两个正整数 \(n\)\(m\)\(n\) 表纸带上格子的个数, \(m\) 表纸带上颜色的种类数。

第二行有 \(n\) 用空格隔开的正整数,第 \(i\) 数字 \(number\) 表纸带上编号为 \(i\) 格子上面写的数字。

第三行有 \(n\) 用空格隔开的正整数,第 \(i\) 数字 \(color\) 表纸带上编号为 \(i\) 格子染的颜色。

Output

共一行,一个整数,表示所求的纸带分数除以 \(10,007\) 所得的余数。

Hint

对 于 全 部 \(10\) 组 数 据 , \(1\leq n\leq 100000, 1\leq m\leq 100000, 1\leq color_i\leq m,1\leq number_i\leq 100000\)

Solution

首先能够推导出 \(x\)\(z\) 的编号一定是奇偶性相同的。

所以想到对于奇数点和偶数点分开统计答案。

拆一下 \((x,y,z)\) 三元组对答案产生的贡献:\((x+z)\times (number_x+number_z)=x\times number_x+x\times number_z+z\times number_x+z\times number_z\)

观察拆完的式子,发现后边三项中与 \(x\) 无关的项都能用前缀和维护。

比如说第二项中的 \(x\times number_z,number_z\) 显然能用前缀和统计。即扫描到 \(x\) 节点时它和后面某个点 \(z\) 对答案在第二项的贡献即为 \((qzh\_number[z]-qzh\_number[x])\times x\)

所以得到了以下这个基本完成的算法:

对于每个颜色,分别开两个数组,存储奇数节点和偶数节点的编号,记为 \(odd\)\(even\)

对于每个颜色中的 \(even\)\(odd\),再开三个前缀和数组分别维护 \(number_z,z,z\times number_z\) 的和。

然后扫描每个颜色,对每个颜色中存储的每个编号从头到尾扫一遍,答案加上这个点之后的所有点与这个点组成的三元组的贡献即可。

Code

#include<cstdio> #include<vector> #include<cctype> #define N 100005 #define mod 10007 #define int long long int ans; int n,m; int num[N]; int col[N]; bool vis[N]; std::vector<int> even[N],odd[N]; std::vector<int> qzh1[N],qzh2[N],qzh3[N]; std::vector<int> qzh4[N],qzh5[N],qzh6[N]; inline char nc(){ static const int BS=1<<22; static unsigned char buf[BS],*st,*ed; if(st==ed) ed=buf+fread(st=buf,1,BS,stdin); return st==ed?EOF:*st++; } //#define nc getchar inline int getint(){ char ch; int res=0; while(!isdigit(ch=nc())); while(isdigit(ch)){ res=(res<<1)+(res<<3)+(ch^48); ch=nc(); } return res; } signed main(){ n=getint(),m=getint(); for(int i=1;i<=n;i++) num[i]=getint(); for(int i=1;i<=n;i++){ col[i]=getint(); if(i&1){ odd[col[i]].push_back(i); int a=qzh1[col[i]].size(); if(!qzh1[col[i]].empty()) qzh1[col[i]].push_back((qzh1[col[i]][a-1]+num[i])); else qzh1[col[i]].push_back(num[i]); a=qzh2[col[i]].size(); if(!qzh2[col[i]].empty()) qzh2[col[i]].push_back((qzh2[col[i]][a-1]+i)); else qzh2[col[i]].push_back(i); a=qzh3[col[i]].size(); if(!qzh3[col[i]].empty()) qzh3[col[i]].push_back((qzh3[col[i]][a-1]+i*num[i])); else qzh3[col[i]].push_back((i*num[i])); } else{ even[col[i]].push_back(i); if(!qzh4[col[i]].empty()) qzh4[col[i]].push_back((qzh4[col[i]][qzh4[col[i]].size()-1]+num[i])); else qzh4[col[i]].push_back(num[i]); if(!qzh5[col[i]].empty()) qzh5[col[i]].push_back((qzh5[col[i]][qzh5[col[i]].size()-1]+i)); else qzh5[col[i]].push_back(i); if(!qzh6[col[i]].empty()) qzh6[col[i]].push_back((qzh6[col[i]][qzh6[col[i]].size()-1]+i*num[i])); else qzh6[col[i]].push_back((i*num[i])); } } for(int k=1;k<=n;k++){ if(vis[col[k]]) continue; vis[col[k]]=1; for(int i=0;i<odd[col[k]].size();i++){ int p=odd[col[k]].size()-i-1; (ans+=odd[col[k]][i]%mod*num[odd[col[k]][i]]%mod*p%mod)%=mod; (ans+=odd[col[k]][i]%mod*(qzh1[col[k]][qzh1[col[k]].size()-1]-qzh1[col[k]][i])%mod)%=mod; (ans+=num[odd[col[k]][i]]%mod*(qzh2[col[k]][qzh2[col[k]].size()-1]-qzh2[col[k]][i])%mod)%=mod; (ans+=qzh3[col[k]][qzh3[col[k]].size()-1]-qzh3[col[k]][i])%=mod; } for(int i=0;i<even[col[k]].size();i++){ int p=even[col[k]].size()-i-1; (ans+=even[col[k]][i]%mod*num[even[col[k]][i]]%mod*p%mod)%=mod; (ans+=even[col[k]][i]%mod*(qzh4[col[k]][qzh4[col[k]].size()-1]-qzh4[col[k]][i])%mod)%=mod; (ans+=num[even[col[k]][i]]%mod*(qzh5[col[k]][qzh5[col[k]].size()-1]-qzh5[col[k]][i])%mod)%=mod; (ans+=qzh6[col[k]][qzh6[col[k]].size()-1]-qzh6[col[k]][i])%=mod; } } printf("%lld\n",ans%mod); return 0; }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zyppdd.html