3. 求和
难度级别:B; 运行时间限制:1000ms; 运行空间限制:51200KB; 代码长度限制:2000000B
题目描述
一条狭长的纸带被均匀划分出了n个格子,格子编号从1到n。每个格子上都染了一种颜色colori用[1,m]当中的一个整数表示),并且写了一个数字numberi。
5
|
5
|
3
|
2
|
2
|
2
|
|
编号
|
1
|
2
|
3
|
4
|
5
|
6
|
定义一种特殊的三元组:(x, y, z),其中x,y,z都代表纸带上格子的编号,这里的三元组要求满足以下两个条件:
组要求满足以下两个条件:
1. xyz是整数,x<y<z,y-x=z-y
2. colorx=colorz
满足上述条件的三元组的分数规定为(x+z)*(numberx+numberz)。整个纸带的分数规定为所有满足条件的三元组的分数的和。这个分数可能会很大,你只要输出整个纸带的分数除以10,007所得的余数即可。
【输入输出样例1】
sum.in
|
sum.out
|
|||||
6
|
2
|
82
|
||||
5
|
5
|
3
|
2
|
2
|
2
|
|
2
|
2
|
1
|
1
|
2
|
1
|
【输入输出样例1 说明】 纸带如题目描述中的图所示。
所有满足条件的三元组为:(1,3,5),(4,5,6)。
所以纸带的分数为(1+5)* (5+2)+ (4+6) *(2+2)=42+40=82。
【输入输出样例2】
sum.in
|
sum.out
|
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
|
1388
|
【数据说明】
对于第 1 组至第 2 组数据, 1 ≤ n ≤ 100, 1 ≤ m ≤ 5;
对于第 3 组至第 4 组数据, 1 ≤ n ≤ 3000, 1 ≤ m ≤ 100;
对于第 5 组至第 6 组数据, 1 ≤ n ≤ 100000, 1 ≤ m ≤ 100000,且不存在出现次数超过 20 的颜色;
对 于 全 部 10 组 数 据 , 1 ≤ n ≤ 100000, 1 ≤ m ≤ 100000, 1 ≤ colori ≤ m,1≤ numberi ≤100000
输入
第一行是用一个空格隔开的两个正整数n和m,n表纸带上格子的个数,m表纸带上颜色的种类数。
第二行有n用空格隔开的正整数,第i数字numberi表纸带上编号为i格子上面写的数字。
第三行有n用空格隔开的正整数,第i数字colori表纸带上编号为i格子染的颜色。
输出
共一行,一个整数,表示所求的纸带分数除以10,007 所得的余数。
样例输入
6 2 5 5 3 2 2 2 2 2 1 1 2 1
样例输出
82
数学不好的人就别往下看了(友情提示)。
这题一看就是数学问题。求彩带分数和的式子需要运用一点数学思维化简(化简成计算机能快速算出的)
比如说:
设同奇偶且同一种颜色的每个格子中的格子编号为a,b,c,d,....,分数为aa,bb,cc,dd,...
由于这些格子中要两两计算分数并相加,因此我们来看看能不能把这个数学计算化简下
有两个格子满足条件时的分数和是
(a+b)*(aa+bb)
(=0*(a*aa+b*bb)+(a+b)*(aa+bb))
有三个格子满足条件时的分数和是
(a+b)*(aa+bb)+(a+c)*(aa+cc)+(b+c)*(bb+cc)
=a*aa+b*bb+c*cc+a*(aa+bb+cc)+b*(aa+bb+cc)+c*(aa+bb+cc) 【把上面那个式子的因式全都分解开,再合并一下,就能合成这样,没难度】
=a*aa+b*bb+c*cc+(a+b+c)*(aa+bb+cc)
(=1*(a*aa+b*bb+c*cc)+(a+b+c)*(aa+bb+cc))
有四个格子满足条件时的分数和是
(a+b)*(aa+bb)+(a+c)*(aa+cc)+(a+d)*(aa+dd)+(b+c)*(bb+cc)+(b+d)*(bb+dd)+(c+d)*(cc+dd)
=2*(a*aa+b*bb+c*cc+d*dd)+a*(aa+bb+cc+dd)+b*(aa+bb+cc+dd)+c*(aa+bb+cc+dd)+d*(aa+bb+cc+dd)
=2*(a*aa+b*bb+c*cc+d*dd)+(a+b+c+d)*(aa+bb+cc+dd)
相信接下来大家已经发现规律了:
正常的像(a+b+c+...)*(aa+bb+cc+...)这样的因式的增项就不说了,主要是注意每多一个格子满足条件时,每个格子就多加一次自身的编号和数字((?)*(a*aa+b*bb+...)
因此用数(哲♂)学做法:
设ci为格子颜色,j为0时表示这些三元组的x,z均为偶数,j为1时则均为奇数。
设之前出现过的与之同奇偶p同颜色ci的格子数设为cnt[ci][p],
格子序号和color[ci][0][p],格子数字和color[ci][1][p],格子序号与数字之积之和为color[ci][2][p]。
当所有格子(所有颜色的格子)满足条件时,分数和为
for(i=1;i<=m;i++)
for(j=0;j<=1;j++){
sum+=color[i][0][j]*color[i][1][j]+((cnt[i][j]-2)*color[i][2][j]);
sum%=10007;
}
#include<iostream>
#include<cstring>
#define maxn 100005
using namespace std;
long long color[maxn][3][2],number[maxn],cnt[maxn][2],n,m,sum;
/*
之前出现过的与之同奇偶p同颜色ci的格子数设为cnt[ci][p],
格子序号和color[ci][0][p],格子数字和color[ci][1][p],格子序号与数字之积之和为color[ci][2][p]
*/
int main(){
int cor,i,j;
scanf("%lld%lld",&n,&m);
for(i=1;i<=n;i++) scanf("%lld",&number[i]);
for(i=1;i<=n;i++){
scanf("%d",&cor);
cnt[cor][i&1]++;
(color[cor][0][i&1]+=i)%=10007;
(color[cor][1][i&1]+=number[i])%=10007;
(color[cor][2][i&1]+=number[i]*i)%10007;
}
for(i=1;i<=m;i++)
for(j=0;j<=1;j++){
sum+=(color[i][0][j]*color[i][1][j])%10007+((cnt[i][j]-2)*color[i][2][j])%10007;
sum%=10007;
}
printf("%lld
",sum);
system("pause");
return 0;
}
我也查了网上别人的题解,我相信我这是最详细的了,因为我抠了一个多小时这题→_→