HDU 5993
大致题意:
给你N堆娃娃,第i堆娃娃数是ai,你有两个操作,一是将相邻的娃娃堆合并成一个,二是将一个娃娃堆分成两堆,这两堆娃娃个数可以不等。现在要求你用这两个操作将N堆人变成k堆人,并且每堆人数要相等,问需要的最少操作数,如不能达成,则输出-1。
大致思路:
首先我们能知道,变化后每堆娃娃数肯定是原娃娃总数对k的平均数。如果不能整除,那么要输出-1;
如果能整除,我们就先求出平均数avr,定义变量ans为0。
然后从第一个ai开始遍历,如果ai等于avr,就continue。
否则ai要是少于avr,我们就将ai与下一个a[i+1]合并,ans++。
要是ai大于avr,我们就求ai能分成几个avr,假设能分成p个而且不剩(avr%p==0),那么ans+=p-1。但是如果ai分完p个avr后还剩下q个呢? 那ans+=p, 再将这q个合并到a[i+1],ans再加1;
最后输出ans。
代码如下:
#include<stdio.h>
#include<iostream>
using namespace std;
long long a[100005];
int main()
{
int t;
scanf("%d",&t);
int cas=1;
while(t--)
{
int n,k;
scanf("%d%d",&n,&k);
long long sum=0;
for(int i=1; i<=n; i++)
{
scanf("%lld",&a[i]);
sum+=a[i];
}
printf("Case #%d: ",cas++);
if(sum%(long long)k)
{
printf("-1\n");
continue;
}
long long avr=sum/(long long)k;
long long ans=0;//注意是long long哦。。。
for(int i=1; i<=n; i++)
{
if(a[i]==avr)continue;//等于的话,我们不用管它了。。
if(a[i]>avr)
{
int p=a[i]/avr;//看能分成几个avr
ans+=p;
int q=a[i]%avr;
if(q==0)ans--;//能整除的话,p-1次就可以分完了。
else
{
a[i+1]+=q;//将剩下的q个合并到下一堆。
ans++;
}
}
else if(a[i]<avr)
{
a[i+1]+=a[i];
ans++;
}
}
printf("%lld\n",ans);
}
**************************************************************************************************
}