[蓝桥杯]K倍区间(c++超详解)
资源限制
时间限制:1.0s 内存限制:256.0MB
给定一个长度为N的数列,A1, A2, ... AN,如果其中一段连续的子序列Ai, Ai+1, ... Aj(i <= j)之和是K的倍数,我们就称这个区间[i, j]是K倍区间。
你能求出数列中总共有多少个K倍区间吗?
输入格式
-----
第一行包含两个整数N和K。(1 <= N, K <= 100000)
以下N行每行包含一个整数Ai。(1 <= Ai <= 100000)
输出格式
-----
输出一个整数,代表K倍区间的数目。
例如,
输入格式
5 2
1
2
3
4
5
程序应该输出:
6
资源约定:
峰值内存消耗(含虚拟机) < 256M
CPU消耗 < 2000ms
请严格按要求输出,不要画蛇添足地打印类似:“请您输入...” 的多余内容。
注意:
main函数需要返回0;
只使用ANSI C/ANSI C++ 标准;
不要调用依赖于编译环境或操作系统的特殊函数。
所有依赖的函数必须明确地在源文件中 #include <xxx>
不能通过工程设置而省略常用头文件。
提交程序时,注意选择所期望的语言类型和编译器类型。
当时看到这题时的第一反应是用枚举,将这一串数的每一个区间都遍历一遍,于是有了如下的代码
#include <bits/stdc++.h>
using namespace std;
long long a[100000];
int main()
{int n,k;int sum=0,cnt=0;cin>>n>>k;for(int i=0;i<n;i++){cin>>a[i];}for(int i=0;i<n;i++){sum=0;for(int j=i;j<n;j++){sum+=a[j];if(sum%k==0){cnt++;}}}cout<<cnt;return 0;
}
提交后直接超时,过了两个测试点(后面的测试点全部超时),只有28分。
于是参考了其它博客,发现了一种更好的方法,使用前缀和取模。
我们假设n=5;k=2;
输入的5个数为1,2,3,4,5的话
程序输出6 这6种情况分别是123 1234 2345 345 2 4;
若我们将前i项和的模存到一个数组mod[i]中,mod[1]表示前一项的和的模,mod[2]表示前两项的和的模,以此类推,再将mod[i]相同的个数用一个数组add[mod[i]]存起来,只需要计算C 2 add[i](高中数学的排列组合,2在上面,add[i]在下面)再加上add[0]的所有结果,便可求得正确答案,极大简化了运算时间。
还是上面那个例子:1 2 3 4 5 假如是输入这5个数
可得mod[1]=1(1%2=1) mod[2]=1((1+2)%2=1) mod[3]=0 mod[4]=0 mod[5]=1
mod=1的个数有3个,mod=0的个数有2个,所以add[0]=2,add[1]=3;
我们先看mod=0的时候,所对应的数是3,4,在(3,4]区间中(注意是左开右闭),4%2=0满足条件,
mod=1的时候,所对应的数是1,2,5,在(1,2]区间中,2%2=0满足条件,(1,5]区间中,2345满足条件(2+3+4+5)%2=0,在(2,5]区间中,345满足条件。
所以可以得出结论,从每一种前缀和(所选两个数的中间的数的和)的情况中任意选择两个数组成的区间都满足是k倍区间,其计算方法其实就是排列组合,上面的例子即可表示为C2 2加上C2 3结果为1+3=4,但实际结果有6种,是由于区间是左开右闭的,加上add[0]的所有结果也就是2和4两种,相当于区间左闭右闭,这两个数本身构成一个k倍区间,4+2=6,刚好是正确答案。
于是可得如下代码:
#include <bits/stdc++.h>
using namespace std;
long long mod[100010]={0},add[100010]={0};
int main()
{int n,k,a;long long cnt=0;cin>>n>>k;for(int i=1;i<=n;i++){cin>>a;mod[i]=(mod[i-1]+a)%k;add[mod[i]]++;}for(int i=0;i<n;i++){cnt+=add[i]*(add[i]-1)/2;//排列组合}cout<<cnt+add[0];return 0;
}
提交后也是直接100分过了,当然要是第一次接触这类题,感觉这种做法还是很难想的,害,算法之路还是十分漫长啊~
[蓝桥杯]K倍区间(c++超详解)相关推荐
- 蓝桥杯 k倍区间 前缀和
参考代码: #include<bits/stdc++.h> using namespace std; typedef long long ll; int array[100005], t[ ...
- [蓝桥杯]连号区间数[题目详解]
题目描述 小明这些天一直在思考这样一个奇怪而有趣的问题: 在1~N的某个全排列中有多少个连号区间呢?这里所说的连号区间的定义是: 如果区间[L, R] 里的所有元素(即此排列的第L个到第R个元素)递增 ...
- 地宫寻宝java_蓝桥杯 2014年 第五届 迷宫寻宝 详解(JAVA)
蓝桥杯 2014年 第五届 迷宫寻宝 详解(JAVA) 基础思路(DFS) package provincial_2014B; import java.util.Scanner; /** * 该题有两 ...
- 蓝桥杯 试题 算法训练 礼物 C++ 详解
题目: JiaoShou在爱琳大陆的旅行完毕,即将回家,为了纪念这次旅行,他决定带回一些礼物给好朋友. 在走出了怪物森林以后,JiaoShou看到了排成一排的N个石子. 这些石子很漂亮,JiaoSho ...
- 蓝桥杯JAVA-28.前缀和与差分详解
个人博客 www.tothefor.com 蓝桥杯复习知识点汇总 目录 开始之前,推荐先看一下总结.再看内容.也许会帮你更好的理解. 前缀和是指某序列的前n项和,可以把它理解为数学上的数列的前n项和, ...
- 蓝桥杯2013JAVA_B省赛真题详解
1.世纪末的星期,枚举每个世纪末,判断是否为星期天 Calendar 2.马虎的算式 枚举每个位上的数字,组合判断 3.振兴中华 找重复中的变化,找边界 4.黄金连分数 1.理解问题等价于斐波那契的n ...
- 线段树区间扫描线超详解,一篇文章搞懂扫描线
怨念 这个专题其实不难,但是翻了一圈网上的博客,写得是云里雾里,我打算用一篇博客把它讲明白 前序知识 能看懂这篇文章需要: 线段树基础知识. 线段树染色问题基本概念. 离散化操作 目标 首先这个扫描线 ...
- 2016蓝桥杯C++A:快速排序(详解版,很快掌握)
四.题目:快速排序 填空题 排序在各种场合经常被用到. 快速排序是十分常用的高效率的算法. 其思想是:先选一个"标尺", 用它把整个队列过一遍筛子, 以保证:其左边的元素都不大于它 ...
- 2014蓝桥杯:地宫取宝(DFS详解)
八.题目;地宫取宝 问题描述 X 国王有一个地宫宝库.是 n x m 个格子的矩阵.每个格子放一件宝贝.每个宝贝贴着价值标签. 地宫的入口在左上角,出口在右下角. 小明被带到地宫的入口,国王要求他只能 ...
最新文章
- 为什么分布式一定要有一致性方案?
- 华为将开源挑战 Oracle 的 AI 原生数据库 GaussDB
- android万年历有什么作用,基于android的万年历农历怎么算
- Steam 导入已下载好的游戏
- 嵌入式linux 添加中断,《嵌入式linux应用程序开发完全手册》中断控制器操作(外部中断)学习笔记...
- c6011取消对null指针的引用_C++中的野指针及其规避方法
- Condition - Java多线程编程
- 关于spark-shell和scala关系的一些个人想法
- Swift数据类型简介(二)
- 扫雷游戏制作学习过程
- java字节流转字符串_字节流与字符流的区别及相互转换
- vue饼图组件_vue写一个图表组件(1)----饼图
- JAVA EE 开发中 常用的API包
- 【语法】NSMutableArray可变数组
- Apache Flink 进阶(八):详解 Metrics 原理与实战
- 德清租房软件测试,门头沟实习生出租房
- java integer long 转换_java - 将Integer转换为Long
- macOS升级node
- ColorOS 13流畅吗?看OPPO在系统上做了哪些升级?
- 自制Arduino便携式超声波测距仪
热门文章
- 美国不会想到,去年对中兴动手,反而逼出了中国的造芯潮!
- Linux下的文件目录及其作用
- sys_kill系统调用
- 最后一名真正的黑客,让微软高管睡不着的人
- ArcGIS NetWork使用经验整理
- 奥运排行榜 (25分) ---排序
- 中国大学程序设计入门c语言答案,中国大学MOOC课程《程序设计入门——C语言》 第8周编程练习...
- 整站翻译,英文网页批量翻译成中文
- 招聘季,面试前知道RocketMQ这二十三点,大厂面试稳了
- tplink错误代码51215_tplink路由器升级失败显示代码18005怎么办