写点什么

贤鱼的刷题日常 --P2671 [NOIP2015 普及组] 求和

作者:贤鱼很忙
  • 2022-10-12
    新疆
  • 本文字数:2015 字

    阅读完需:约 7 分钟

贤鱼的刷题日常--P2671 [NOIP2015 普及组] 求和

🏆今日学习目标:🍀学会求和题目✅创作者:贤鱼


@TOC

题目

[NOIP2015 普及组] 求和

题目背景

NOIP2015 普及组 T3

题目描述

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



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


  1. 是整数,



满足上述条件的三元组的分数规定为。整个纸带的分数规定为所有满足条件的三元组的分数的和。这个分数可能会很大,你只要输出整个纸带的分数除以所得的余数即可。

输入格式

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


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


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

输出格式

一个整数,表示所求的纸带分数除以所得的余数。

样例 #1

样例输入 #1

6 25 5 3 2 2 22 2 1 1 2 1
复制代码

样例输出 #1

82
复制代码

样例 #2

样例输入 #2

15 45 10 8 2 2 2 9 9 7 7 5 6 4 2 42 2 3 3 4 3 3 2 4 4 4 4 1 1 1
复制代码

样例输出 #2

1388
复制代码

提示

【输入输出样例 1 说明】


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


所有满足条件的三元组为:


所以纸带的分数为


对于第 组至第 组数据,


对于第 组至第 组数据,


对于第 组至第组数据, ,且不存在出现次数超过的颜色;


对 于 全 部 组 数 据 ,

思路

这道题我们分为两种方法讲 1:20 分做法:


题目==要求==中说的非常详细

  1. 是整数,

  2. 所以我们三层循环遍历一遍肯定能全部找到但是看看数据范围,100000?三层循环要么我炸要么时间复杂度炸所以这种方法只有 40 分


2:<font color="gree">AC</font>做法:


需要用到一些数学内容(童鞋们不要慌,下面有详细解说)首先明确一下目标 1 压缩压缩下标 2 压缩压缩颜色==啊对,就这俩,不多吧,下面来看具体:==因为 是整数,所以 所以 $x+y 无论如何都为偶数(任何数字 2 都为偶数)i_n,当前数字的值为 num_n(i_1+i_2)(n_1+n_2)+(i_1+i_3)(n_1+n_3)+(i_1+i_4)(n_1+n_4)+......(i_1+i_n)(n_1+n_n)i_1n_1+i_1n_2+i_1n_1+i_1n_3...+i_1n_ni_1*(n_2+....+n_n)+(n-1)i_1n_1i_1*(n_2+...n_n)+i_1n_1+(n-1)i_1n_1-i_1n_1i_1*(n_1+..n_1)+(n-2)i_1n_1$这样子是不是就做完了,这里我们可以通过前缀和提前获取我们需要的东西,下面来看看代码

代码

==20 分做法,不想看的可以跳过==


#include<cmath>#include<cstdio>#include<iostream>#include<cstring>using namespace std;int n,c,num[1000001],col[100001];int main(){cin>>n>>c;for(int i=1;i<=n;i++){  cin>>num[i];}for(int i=1;i<=n;i++){  cin>>col[i];}int ans=0;for(int i=1;i<=n;i++){  for(int j=i+1;j<=n;j++){    for(int k=j+1;k<=n;k++){      if(j-i==k-j&&col[i]==col[k]){//三层循环处理找答案        ans+=(i+k)*(num[i]+num[k]);        ans%=10007;      }    }  }}cout<<ans%10007;}
复制代码


==<font color="gree">AC</font>做法:==


#include<cmath>#include<cstdio>#include<iostream>#include<cstring>using namespace std;int n,c,num[1000001],col[100001];//num储存所有数字,col储存颜色int main(){cin>>n>>c;for(int i=1;i<=n;i++){  cin>>num[i];}int z[101010][3];//这里储存每个组有多少数字int sum[1010100][3];//这里储存前缀和for(int i=1;i<=n;i++){  cin>>col[i];  z[col[i]][i%2]++;//这个组的数字加1  sum[col[i]][i%2]=(sum[col[i]][i%2]+num[i])%10007;//这个组前面所有的数字和加上当前加入的数字
}int ans=0;for(int i=1;i<=n;i++){ans=(ans+i*(sum[col[i]][i%2]+(z[col[i]][i%2]-2)*num[i]%10007))%10007;//这里就是按照上面题目所说处理}cout<<ans%10007;}
复制代码


<font size="5">🏆结束语</font>:


如果有需要的话可以订阅专栏,持续更新🔥一文了解数据库操作--mysql(25分钟)欢迎你的到来🔥



发布于: 刚刚阅读数: 6
用户头像

贤鱼很忙

关注

为了未来奋斗中 2022-09-28 加入

主修网络安全和c++方面内容,时常提供题解和网络安全方面知识

评论

发布
暂无评论
贤鱼的刷题日常--P2671 [NOIP2015 普及组] 求和_10月月更_贤鱼很忙_InfoQ写作社区