zoukankan      html  css  js  c++  java
  • [蓝桥杯][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;
    }
    
  • 相关阅读:
    Quartz.NET-2.3.3 各种 数据库配置 类别大全
    C#获取当前路径的七种方法 【转载】
    BCB 如何拦截TAB键消息
    用union 和 struct 位域操作
    表值函数
    C#中 委托和事件的关系
    关于C++ Builder Codegurad 问题的排查。
    存储过程中使用事务的“正规”写法
    C++ 中对vector<T*> 数组的查找和排序
    BCB 中 Application->CreateForm 和 New 的一个区别
  • 原文地址:https://www.cnblogs.com/fxzemmm/p/14847988.html
Copyright © 2011-2022 走看看