codeforces1428E Carrots for Rabbits

https://codeforces.com/contest/1428/problem/E

一打开榜发现E比D过得还多,就果断先写E

可以发现一个胡萝卜如果要分为num[i]段,那么肯定是平均更好,就可以轻松算出来a[i]分成Num[i]段的最小的平方和

然后我们就贪心地去选择选择哪一个胡萝卜从分成num[i]段变成num[i]+1段,他能减少的代价最大就行了

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

const int maxl=3e5+10;

int n,m,k,cnt,tot,cas;ll ans;
ll a[maxl];
int num[maxl];
bool vis[maxl];
char s[maxl];
typedef pair <ll,int> p;
priority_queue<p> q;

inline ll calc(ll x,int i)
{
	ll d,res;
	d=x/i;res=x%i;
	return d*d*(i-res)+(d+1)*(d+1)*res;
}

inline void prework()
{
	scanf("%d%d",&n,&k);
	for(int i=1;i<=n;i++)
		scanf("%lld",&a[i]);
	ans=0;
	for(int i=1;i<=n;i++)
	{
		ans+=a[i]*a[i];num[i]=1;
		if(a[i]==1)
			q.push({0ll,i});
		else
			q.push({calc(a[i],1)-calc(a[i],2),i});
	}
}

inline void mainwork()
{
	p d;int id;
	for(int i=n+1;i<=k;i++)
	{
		d=q.top();q.pop();
		ans-=d.first;id=d.second;
		num[id]++;
		if(a[id]<=num[id])
			q.push({0ll,id});
		else	
			q.push({calc(a[id],num[id])-calc(a[id],num[id]+1),id});
	}
	
}

inline void print()
{
	printf("%lld\n",ans);
}

int main()
{
	int t=1;
	//scanf("%d",&t);
	for(cas=1;cas<=t;cas++)
	{
		prework();
		mainwork();
		print();
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/liufengwei1/article/details/109211002
今日推荐