CF1070K Video Posts - 题解
题目大意
能否将一个长度为 \(n\) 的数列分成 \(k\) 段,使每段的和相等?如果能,输出每段的长度。
解析
Yes 的情况
我们可以首先求出每段的和。我们知道,共 \(k\) 段,每段的和相等,所以每段的和就是总长度除以 \(k\)。
然后,我们可以在求出每段和后,重新扫一遍原数列,累加和并记录长度。当累加到等于每段和后,累加的长度就是答案。
No 的情况
对于 No 的情况,我们可以发现,有以下两种可能:
-
每段的和不是整数,即总长度不能被 \(k\) 整除。
-
累加长度时无法恰好等于每段和。
对于第二种情况,需要在扫第二遍的途中判断,所以在第二遍扫完之前不能判断是 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 迁移至博客园。
本文采用 「CC-BY-NC 4.0」 创作共享协议,转载请注明作者及出处,禁止商业使用。
作者:Jerrycyx,原文链接:https://www.cnblogs.com/jerrycyx/p/19065118

浙公网安备 33010602011771号