• [蓝桥杯][2017年第八届真题]k倍区间 (前缀和)


    [蓝桥杯][2017年第八届真题]k倍区间

    时间限制: 1Sec 内存限制: 128MB 提交: 671 解决: 158

    题目描述
    给定一个长度为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

    题干要求我们求得是k的倍数区间,我们可以用s[i]储存前i个数,用s[i]-s[j-1]表示区间【j,i】的和。然后我们利用两层for循环枚举区间范围,寻找符合要求的区间。至此,问题似乎解决了,But题干所给的数据范围是1e5,双层循环肯定会超时,那么怎么办呢?我们来分析一下问题,题干让我们寻找的是满足(s[i]-s[j-1])%k= =0的情况,上述算法之所以会超时,原因在于需要枚举i,j的范围,那么我们是否换种思路。即求s[i]%k= =s[j-1]%k的情况有多少。因为求s[i]%k= =s[j-1]%k的情况并不需要进行枚举,只需把s[i]%=k储存 桶排序 最后再加上这个数本身就是k的倍数的情况即可。
    代码如下:

    #include <stdio.h>
    long long a[100005],s[100005],v[100005],n,k,ans,temp;      //满足条件 (s[r]-s[l-1])%k==0 即(s[r]%k)==(s[i-1]%k) 则符合条件 
    int main()
    {
    	scanf("%lld%lld",&n,&k);
    	for(int i=0;i<n;i++)
    	{
    		scanf("%lld",&temp);
    		s[i]=(s[i-1]+temp)%k;
    		ans+=v[s[i]];
    		v[s[i]]++;
    	}
    	ans+=v[0];
    	printf("%lld",ans);
    	return 0;
    }
    
  • 相关阅读:
    MySQL索引原理及慢查询优化
    MySQL单表百万数据记录分页性能优化
    linux下crontab命令的使用
    php递归读取目录
    php实现函数重载
    php数组常见的几种遍历方法
    ArtTemplate 使用笔记
    打算换工作的伙伴们,快来看啦,各种职位,随便挑咯...
    看看国外的javascript题目,你能全部做对吗?(分享)
    逛园子,看到个练习题,小试了一把(淘宝ued的两道小题)
  • 原文地址:https://www.cnblogs.com/fxzemmm/p/14847988.html
Copyright © 2020-2023  润新知