一维前缀和--k倍区间(蓝桥)

文章介绍了通过同余定理和前缀和技巧解决数组问题,对比了暴力枚举和优化后的代码,强调了数学理论在编程中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录:

【题目描述】

【AC代码】

【同余定理】

【作者思路】

【一些闲话】

【题目描述】

 【AC代码】

在此先贴上博主的暴力代码,超时,只有28分

#include <bits/stdc++.h>
using namespace std;
int arr[100000];
int main()
{
	int n,k;
	cin>>n>>k;
	for(int i=0;i<n;i++)
	{
		cin>>arr[i];//输入
	}
	int f=0;
	int cnt=0;
	for(int i=0;i<n;i++)//暴力枚举每一个元素作为起始点向后相加的集合值
	{
		f=arr[i];//取出起始元素
		if(f%k==0)//判断单个元素是否符合k倍
		{
			cnt++;
		}
		for(int j=i+1;j<n;j++)//以i为起点向后查找
		{
			f+=arr[j];//范围一直向后扩大
			if(f%k==0)//符合k倍更新答案
			{
				cnt++;
			}
		}
	}
	cout<<cnt;
	return 0;
}

接下来是100分代码

利用的前缀和以及同余定理

#include <bits/stdc++.h>
#define int long long
using namespace std;
int ans[100000];
signed main()
{
	int n,k;
	cin>>n>>k;
	int f=0;
	for(int i=0;i<n;i++)
	{
		int a;
		cin>>a;
		f+=a;
		ans[f%k]++;//统计模k值相等的区间数量
	} 
	int cnt=0;
	for(int i=0;i<k;i++)
	{
		cnt+=((ans[i]-1)*ans[i])/2;//排列组合,在模k值相等的区间里找两个区间搭配
	}
	cout<<cnt+ans[0];//为什么加上ans[0],下文讲
	return 0;
}

【同余定理】

 当有两段区间除以 K 的余数相等时,它们的差就一定是 K 的倍数

【作者思路】

为什么要加上ans[0],ans[0]表示的意思是所有前缀和模k的值为0的前缀和个数,例如k=2,有前缀和f=4,6,8,所以ans[0]=3。此时最后一个for循环中计算的是两个前缀和的搭配,但是ans[0]中的区间不需要搭配,自己(一个前缀和)便符合题意,所以要加上只需要一个前缀和便符合题意的情况,因此输出应为cnt+ans[0]

【一些闲话】

欢迎各位指出错误,提出问题,作者一定尽力解答

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值