题目大意
一条狭长的纸带被均匀划分出了 n个格子,格子编号从 1 到 n。每个格子上都染了一种颜色color_i(用 [1,m]当中的一个整数表示),并且写了一个数字 number_i。
(这图不用想,也是从SSL学校网站上抠下来的)
定义一种特殊的三元组:(x,y,z),其中 x,y,z 都代表纸带上格子的编号,这里的三元组要求满足以下两个条件:
1. x,y,z是整数,x<y<z,y−x=z−y
2. color_x=color_z
满足上述条件的三元组的分数规定为 (x+z)×(number_x+number_z) 。整个纸带的分数规定为所有满足条件的三元组的分数的和。这个分数可能会很大,你只要输出整个纸带的分数除以 10,007 所得的余数即可。
输入格式
第一行是用一个空格隔开的两个正整数 n和m, n表纸带上格子的个数,m表纸带上颜色的种类数。
第二行有n个用空格隔开的正整数,第 i个数字number表纸带上编号为i的格子上面写的数字。
第三行有 n个用空格隔开的正整数,第i个数字color表纸带上编号为i的格子商染的颜色。
1<=n<=1e5,1<=color_i<=m<=1e5,1<=number_i<=1e5
输出格式
一个整数,表示所求的纸带分数除以 10007所得的余数。
输入样例
【输入样例1】
6 2
5 5 3 2 2 2
2 2 1 1 2 1
【输入样例2】
15 4
5 10 8 2 2 2 9 9 7 7 5 6 4 2 4
2 2 3 3 4 3 3 2 4 4 4 4 1 1 1
输出样例
【输出样例1】
82
//样例说明:
纸带如题目描述中的图所示。
所有满足条件的三元组为: (1, 3, 5), (4, 5, 6)。
所以纸带的分数为(1+5)×(5+2)+(4+6)×(2+2)=42+40=82。
【输入样例2】
1388
基本思路
这题暴力不用说,必超。下面我们来看看数学解法具体是什么样的。
//推导:
y-x=z-y 2*y=x+z x+z为偶数,所以x,z同奇偶
同色同奇偶(可以运算)的格子
P1 P2 P3 P4 (下标i)
X1 X2 X3 X4 (number_i)
S=X1+X2+X3+X4 k=4(有几个格子)
ans= (P1+P2)*(X1+X2)+(P1+P3)*(X1+X3) +(P1+P4)*(X1+X4)+(P2+P3)*(X2+X3) +(P2+P4)*(X2+X4)+(P3+P4)*(X3+X4)
乘法分配
=P1*(3*X1+X2+X3+X4)+P2*(X1+3*X2+X3+X4) +P3*(X1+X2+3*X3+X4)+P4*(X1+X2+X3+3*X4)
=P1*S+P1*2*X1+P2*S+P2*2*X2 +P3*S+P3+2+X3+P4*S+P4*2*X4
Pi*S+Pi*(k-2)*Xi
这题说实话没点观察力是真想不出来。
核心代码
思路注释上去了,去掉注释应该也就二十多行。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
//推导:
//y-x=z-y
//2*y=x+z
//x+z为偶数,所以x,z同奇偶
//同色同奇偶(可以运算)的格子
//P1 P2 P3 P4
//X1 X2 X3 X4
//S=X1+X2+X3+X4
//k=4(有几个格子)
//ans=
//(P1+P2)*(X1+X2)+(P1+P3)*(X1+X3)
//+(P1+P4)*(X1+X4)+(P2+P3)*(X2+X3)
//+(P2+P4)*(X2+X4)+(P3+P4)*(X3+X4)
//
//=P1*(3*X1+X2+X3+X4)+P2*(X1+3*X2+X3+X4)
//+P3*(X1+X2+3*X3+X4)+P4*(X1+X2+X3+3*X4)
//
//=P1*S+P1*2*X1+P2*S+P2*2*X2
//+P3*S+P3+2+X3+P4*S+P4*2*X4
//
//Pi*S+Pi*(k-2)*Xi
const ll mod=10007;
const ll N=1e5+10;
ll n,m,ans,s[N][2],x[N],k[N][2],c[N];
int main(){
ios::sync_with_stdio(false);
cin>>n>>m;
for(int i=1;i<=n;i++) cin>>x[i];
for(int i=1,ci;i<=n;i++){
cin>>c[i];
s[c[i]][i%2]+=x[i];
s[c[i]][i%2]%=mod;//同余定理
k[c[i]][i%2]++;
}
for(int p=1;p<=n;p++){
if(k[c[p]][p%2]<2) continue;
ans+=p*s[c[p]][p%2]+p*(k[c[p]][p%2]-2)*x[p];
ans%=mod;
}
cout<<ans;
return 0;
}