CF1070K Video Posts - 题解

题目大意

能否将一个长度为 \(n\) 的数列分成 \(k\) 段,使每段的和相等?如果能,输出每段的长度。

解析

Yes 的情况

我们可以首先求出每段的和。我们知道,共 \(k\) 段,每段的和相等,所以每段的和就是总长度除以 \(k\)

然后,我们可以在求出每段和后,重新扫一遍原数列,累加和并记录长度。当累加到等于每段和后,累加的长度就是答案

No 的情况

对于 No 的情况,我们可以发现,有以下两种可能:

  1. 每段的和不是整数,即总长度不能被 \(k\) 整除

  2. 累加长度时无法恰好等于每段和

对于第二种情况,需要在扫第二遍的途中判断,所以在第二遍扫完之前不能判断是 Yes 还是 No。故不能一边扫一边输出 Yes 的答案,我们需要把答案记录下来。

\(\textcolor{#52C41A}{\texttt{AC}}\) 代码

#include<cstdio>
using namespace std; 

int n,k;
int a[100005];
int tot,ans[100005],ans_cnt=0;
//ans 记录答案 

int main()
{
	scanf("%d%d",&n,&k);
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&a[i]);
		tot+=a[i];		//tot 记录总和 
	}
	if(tot%k!=0)		//判断 No 的第一种情况 
	{
		printf("No\n");
		return 0;
	}
	tot/=k;				//tot 在此时变成每段的和 
	int sum=0,cnt=0;	//sum 记录当前累加和,cnt记录当前段长度 
	for(int i=1;i<=n;i++)
	{
		sum+=a[i];
		if(sum>tot)		//判断 No 的第二种情况 
		{
			printf("No\n");
			return 0;
		}
		cnt++;
		if(sum==tot)
		{
			ans[++ans_cnt]=cnt;	//记录答案 
			sum=cnt=0;			//清空上一段的数据 
		}
	}
	//到这里还没有被 return 掉,说明这是 Yes 
	printf("Yes\n");
	for(int i=1;i<=ans_cnt;i++)
		printf("%d ",ans[i]);
	return 0;
}

2022-07-06 22:34 撰写于洛谷,2025-08-29 20:24 迁移至博客园。

posted @ 2025-08-29 20:25  Jerrycyx  阅读(6)  评论(0)    收藏  举报