蓝桥杯练习题八 - k倍区间(c++)(二)

简介: 蓝桥杯练习题八 - k倍区间(c++)

1.实时读取数据


        cin >> son[i];


2.获取sum[i]

        if (i != 0)
            sum[i] = (sum[i - 1] + son[i]) % k;
        else
            sum[i] = son[i] % k;

sum[i]我们都能理解,就是累加和嘛,可这里偏偏要%k是什么鬼意思?这里要当心了,一步看不懂,后面的全都看不懂了,我们把sum当做一个存储累加和余数的数组,我再强调一遍,“累加和余数”!!!!


所以:


当i == 0时,sum[i] = son[i] % k,即sum[0] = son[0] % k;


当i == 1时,sum[i] = (sum[i - 1] + son[i])% k,即sum[1] = (sum[0] + son[1]) % k;


记住我说的,sum是余数和,后面你就忘掉那个“和”字,只记住“余数”,然后来展开下上面的公式:

sum[1] = (sum[0] + son[1]) % k;
sum[1] = sum[0] % k + son[1] % k;
sum[1] = sum[0] + son[1] % k; 
//sum[0]已经是余数了,所以%k没有意义,是本身

第一种解法,sumArray存储的是每一项从0开始的当前项的累加和


这里sum存储的就是sumArray存储的是每一项从0开始的当前项余数的累加和


3.先说sum[i] == 0的情况

1.        if (sum[i] == 0)
            ans++;

这个很明显,只要整数取余为0,那必然是符合k区间条件的,这里ans++应该不难理解,因为sum中存储的全是余数,必然不会全是0,有人会有疑惑,假如有多个不为0的余数存在,那么sum[i] == 0这个条件还能成立吗?答案是肯定的,这就是为什么余数也要进行相加的原因:

sum[i] = (sum[i - 1] + son[i]) % k;

余数(被忽略的部分必然被整除了)+余数(被忽略的部分必然被整除了)能被整除就是0,不能被整除就是另一个余数,也有可能和当前余数相等,相等怎么办?看下面:


4.区间计算的重头戏

b[sum[i]]++;
ans += b[sum[i]] - 1;

能不能看得懂就全看这里了!!!


b是什么?


b是用来存储相等的余数出现的次数的!!!


如果余数相等,则对应的i,j相减就把余数减去了,剩下的必定可以整除,这就是一个新的区间!!!


我们从0开始模拟下b:


假设余数为3:


余数3出现1次时:


b[3]++ = 1,说明余数为3的累加和出现1次,这时候没有成对出现,无法用j-i判断是否存在k倍区间;


余数3出现2次时:


b[3]++ = 2,说明余数为3的累加和出现2次,这时候存在1个k倍区间,为什么是1个呢?假设这2个累加和下表分别是i,j,那么有,j-i这个一个区间;


余数3出现3次时:


b[3]++ = 3,说明余数为3的累加和出现3次,这时候存在2个k倍区间,为什么是2个呢?假设这3个累加和下表分别是i,j,k,那么有,k-i,k-j,有人说,不是还有个j-i吗?没错,但是j-i已经在余数出现第2次的时候存在了,不能计算在内;


余数3出现4次时:


b[3]++ = 4,说明余数为3的累加和出现4次,这时候存在3个k倍区间,为什么是3个呢?假设这4个累加和下表分别是i,j,k,l那么有,l-i,l-j,l-k有人说,不是还有个j-i和k-i,k-j吗?没错!你抬头看看余数出现第2,3次的里面有没有没列出来的这三个?所以不能计算在内;


所以,你发现规律了吗?像不像选择排序法里面那样?用最后一个和前面的所有项比较,这还真是选择排序法里德运用。


ans += b[sum[i]] - 1;


这时候,你已经明白了b[sum[i]] 的含义,你可能还需要再消化下......


已经看懂的同学我们继续下一个问题,为什么要减1?


一个余数的时候,区间不成立;


两个相等余数的时候,两两比较,只能有1个;


三个相等余数的时候,最后一位和前两个比较,只有2个,


......


n个相等余数的时候,最后一位和前n-1个比较,只有n-1个.


因为始终有一个要作为参照系,所以只能存在n-1个,上面的举例已经清楚说明了原因。


总结


到这里,今天的学习就要结束了,说实话,这个题真TM难,就这,还被列入了简单之类,😂但是你要是听懂了,你会发现其实也不难,就是一个理念问题,可问题是,这样的理念不是一般人想的出来的。


另外,博主在查找的时候看到有些人的解析里面用到了c(m,n),这是什么呢?


从n个不同的元素中,任取m(m≤n)个元素为一组,叫作从n个不同元素中取出m个元素的一个组合。所以它叫排列组合,记得大学里面高数里讲概率的时候有讲过,相信很多人都忘了。根据这种理论,会有一种新的写法,但思路和第二种是一样的,我们是直接通过从n个余数中找出有几种组合的方式,c(m,n)是根据数学的思维通过公式计算sumArray中存在余数的组合方式:


1  2  3  4  5

son[]

1  2  3  4  5

1  0  1  0  1 每一项整除取余

这里是2个

sum[]

1  3  6  10  15

1  1  0  0   1  累加和整除取余

这里1是c(3,2)=3;

这里0是c(2,2)=1;

2 + 3 + 1 = 6


感兴趣的可以去了解下这种方式,不再赘述,有问题欢迎评论区留言讨论。

目录
相关文章
|
1月前
|
Java C语言 C++
第十四届蓝桥杯集训——练习解题阶段(无序阶段)-ALGO-939 区间最大和
第十四届蓝桥杯集训——练习解题阶段(无序阶段)-ALGO-939 区间最大和
32 0
|
1月前
|
Java C语言 C++
第十四届蓝桥杯集训——练习解题阶段(无序阶段)-ALGO-459 区间求和
第十四届蓝桥杯集训——练习解题阶段(无序阶段)-ALGO-459 区间求和
24 0
|
1月前
|
算法 C++
小唐开始刷蓝桥(五)2016年第七届C/C++ B组蓝桥杯省赛真题
小唐开始刷蓝桥(五)2016年第七届C/C++ B组蓝桥杯省赛真题
|
1月前
|
网络安全
蓝桥杯-网络安全-练习题-crypto-rsa
蓝桥杯-网络安全-练习题-crypto-rsa
蓝桥杯-网络安全-练习题-crypto-rsa
|
1月前
|
算法 测试技术 C++
小唐开始刷蓝桥(八)2013年第四届C/C++ B组蓝桥杯省赛真题
小唐开始刷蓝桥(八)2013年第四届C/C++ B组蓝桥杯省赛真题
|
1月前
|
算法 C++ 数据格式
小唐开始刷蓝桥(七)2014年第五届C/C++ B组蓝桥杯省赛真题
小唐开始刷蓝桥(七)2014年第五届C/C++ B组蓝桥杯省赛真题
|
1月前
|
算法 C++
小唐开始刷蓝桥(六)2015年第六届C/C++ B组蓝桥杯省赛真题
小唐开始刷蓝桥(六)2015年第六届C/C++ B组蓝桥杯省赛真题
|
1月前
|
C语言
蓝桥杯练习题
蓝桥杯练习题包括6道C语言编程题:1. 判断三位数是否为水仙花数;2. 输出区间质因数分解;3. 将秒转换为'H:M:S'格式;4. 判断闰年;5. 删除可被整除元素并排序数组,数字转字母;6. 分类比较两个字符串关系。每题涉及不同逻辑操作,适合编程初学者练习。
26 3
|
1月前
|
人工智能 搜索推荐 C++
小唐开始刷蓝桥(一)2020年第十一届C/C++ B组第二场蓝桥杯省赛真题
小唐开始刷蓝桥(一)2020年第十一届C/C++ B组第二场蓝桥杯省赛真题
|
1月前
|
机器学习/深度学习 存储 人工智能
小唐开始刷蓝桥(三)2018年第九届C/C++ B组蓝桥杯省赛真题
小唐开始刷蓝桥(三)2018年第九届C/C++ B组蓝桥杯省赛真题