第八届蓝桥杯第十题--k倍区间(C语言)

第八届蓝桥杯第十题–K倍区间(C语言)

一.比赛题目

1.题目要求

给定一个长度为N的数列,A1, A2, … AN,如果其中一段连续的子序列Ai, Ai+1, … Aj(i <= j)之和是K的倍数,我们就称这个区间[i, j]是K倍区间。 你能求出数列中总共有多少个K倍区间吗?

2.输入与输出

输入:
第一行包含两个整数N和K。(1 <= N, K <= 100000) 以下N行每行包含一个整数Ai。(1 <= Ai <= 100000)
输出:
输出一个整数,代表K倍区间的数目。
样例输入:
5 2
1
2
3
4
5
样例输出:
6

二.分析过程

1.总体分析

这道题一眼就能看懂,双重for循环,一个i=0到n,一个j=i+1到n,就可以把这个结果求出来;但是就这道题而言,1 <= N, K <= 100000,所以肯定会超时。问题就在于如何节省时间;
在前段时间学习了动规,背包之后,有了填表,拆分成子问题来解决的一种思想。

2.问题分析

就样例输入而言,可以把1-5来进行填表:

序号 1 2 3 4 5
数字 1 2 3 4 5
总和 1 3 6 10 15

因为第一个数字需要考虑1,1+2,1+2+3,1+2+3+4等情况,而最后一个数字仅需要考虑5他本身,所以我们采用逆推的想法来填表:

序号 1 2 3 4 5
数字 1 2 3 4 5
递减总和 15 14 12 9 5

我们得到:第i个递减总和–第i+3个递减总和,就是第i个–第i+2个数字的连续区间之和
例如第二个数字的递减总和–第五个数字的递减总和=第二个到第四个连续区间相加的总和;
第二个数字的递减总和–第四个数字的递减总和=第二个到第三个连续区间相加的总和;

第n个数字:

满足条件
不满足条件
n
sum++
sum不变

第n-1个数字:

满足条件
不满足条件
不满足条件
满足条件
n-1
sum++
an-1-an
sum不变

注:不满足条件时是a[n-1]-a[n],即为倒数第二个;

通过递推,我们发现了第i个开始的连续区间可以用这种方式来表示,所以就能够节约下来双重for循环的时间;
代码如下:

for(int i=n-1;i>=0;i--)
	{
		if(c[i]%k==0)
			sum++;
		for(int j=n-1;j>i;j--)
		{
			if((c[i]-c[j])%k==0)
				sum++;
		}
	}
	//c[i]就是表里面递推的总和;

三.整体代码

#include<stdio.h>

int main()
{
	int n,k;
	scanf("%d %d",&n,&k);
	int sum=0;
		//记录输入数据的总和;
	int count=0;
		//记录k倍区间的数目;
	int a[n],c[n];
	for(int i=0;i<n;i++)
		{
		scanf("%d",&a[i]);
		sum+=a[i];
	}
		//输入数据且计算总和;
	c[0]=sum;
		//第一个数赋值为全部数的总和;
	for(int i=1;i<n;i++)
	{
		c[i]=c[i-1]-a[i-1];
	}
		//递减总和;
	for(int i=n-1;i>=0;i--)
	{
		if(c[i]%k==0)
			count++;
		for(int j=n-1;j>i;j--)
		{
			if((c[i]-c[j])%k==0)
				count++;
		}
	}
		//条件筛选;
	printf("%d",count);
	return 0;
 } 

四.总结

这道题是会了算法思想之后再来看的一道题,虽然没有用到,但是在解决问题的时候递推观察还是挺有帮助的。接下来就要学习其他的算法和做题了。

发布了12 篇原创文章 · 获赞 7 · 访问量 1454

猜你喜欢

转载自blog.csdn.net/weixin_45843077/article/details/104175602