【NOIP2015普及组复赛】题3:求和

题3:求和

【题目描述】

一条狭长的纸带被均匀划分出了 nnn 个格子,格子编号从 111nnn。每个格子上都染了一种颜色coloricolor_icolori (用[1,m][1,m][1m]当中的一个整数表示),并且写了一个数字numberinumber_inumberi
在这里插入图片描述

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

  1. xyzxyzxyz 是整数,x<y<z,y−x=z−yx<y<z,y−x=z−yx<y<zyx=zy
  2. colorx=colorzcolor_x=color_zcolorx=colorz
    满足上述条件的三元组的分数规定为 (x+z)×(numberx+numberz)(x+z)×(number_x+number_z)(x+z)×(numberx+numberz) 。整个纸带的分数规定为所有满足条件的三元组的分数的和。这个分数可能会很大,你只要输出整个纸带的分数除以 10,00710,00710,007 所得的余数即可。

【输入】

第一行是用一个空格隔开的两个正整数 nnnm,nm,nmn 表纸带上格子的个数,mmm 表纸带上颜色的种类数。

第二行有 nnn 用空格隔开的正整数,第 iii 数字 numbernumbernumber 表纸带上编号为 iii 格子上面写的数字。

第三行有 nnn 用空格隔开的正整数,第 iii 数字 colorcolorcolor 表纸带上编号为 iii 格子染的颜色。

【输出】

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

【输入样例1】

6 2
5 5 3 2 2 2
2 2 1 1 2 1

【输出样例1】

82

【输入样例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

【输出样例2】

1388

【样例1说明】

纸带如题目描述中的图所示。

所有满足条件的三元组为: (1,3,5),(4,5,6)(1,3,5),(4,5,6)(1,3,5),(4,5,6)

所以纸带的分数为 (1+5)×(5+2)+(4+6)×(2+2)=42+40=82(1+5)×(5+2)+(4+6)×(2+2)=42+40=82(1+5)×(5+2)+(4+6)×(2+2)=42+40=82

【数据规模】

对于第 111 组至第 222 组数据,1≤n≤100,1≤m≤51≤n≤100,1≤m≤51n100,1m5

对于第 333组至第 444 组数据,1≤n≤3000,1≤m≤1001≤n≤3000,1≤m≤1001n3000,1m100

对于第 555 组至第 666 组数据,1≤n≤100000,1≤m≤1000001≤n≤100000,1≤m≤1000001n100000,1m100000,且不存在出现次数超过 202020 的颜色;

对于全部 101010 组数据,1≤n≤100000,1≤m≤100000,1≤colori≤m,1≤numberi≤1000001≤n≤100000,1≤m≤100000,1≤colori≤m,1≤numberi≤1000001n100000,1m100000,1colorim1numberi100000

【代码如下】:

#include<bits/stdc++.h>
using namespace std;
//ifstream cin("sum.in");
//ofstream cout("sum.ans");
const int mn=100000;
const int mm=100000;
const int p=10007;
int n,m,ans;
int number[mn+1],colour[mn+1];
int s[2][mm+1][4];

void init(){
    cin >> n >> m;
    for(int i=1;i<=n;i++){
    	cin >> number[i];
	}
    for(int i=1;i<=n;i++){
    	cin >> colour[i];
	}
}
void solve(){
    for(int i=1;i<=n;i++){
        int z=i%p,numz=number[i]%p,c=colour[i],t=i%2;
        int count=s[t][c][0]%=p,x=s[t][c][1]%=p,
numx=s[t][c][2]%=p,x_numx=s[t][c][3]%=p;
        ans=(ans+((count*z)%p*numz)%p)%p;
        ans=(ans+x_numx)%p;
        ans=(ans+x*numz)%p;
        ans=(ans+z*numx)%p;
        s[t][c][0]++;
        s[t][c][1]+=z;
        s[t][c][2]+=numz;
        s[t][c][3]+=z*numz;
    }
}
void output(){
    cout << ans;
    //fclose(stdin);
    //fclose(stdout);
}
int main(){
    init();
    solve();
    output();
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lpstudio

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值