题目大意
题目思路
感性理解一下,将一个数的平方变成多个数平方的和,为了使代价最小,这些数的大小应该尽可能的平均。
我们可以将 ∣ b i − a i ∣ |b_i-a_i| ∣bi−ai∣放入大根堆,同时将这个数划分的次数以及多划分一段减少的代价放入,按减少的代价从大到小取。
总时间复杂度为 O ( m log n ) \mathcal O(m \log n) O(mlogn)。
具体实现参考代码。
#include<bits/stdc++.h>
using namespace std;
int n,m;
long long a[100000+10];
__int128 ans=0;
struct node
{
long long x,l,val;
bool operator<(const node &a)const
{
return val<a.val;
}
};
priority_queue<node> p;
const long long mod=998244353;
long long read()
{
long long s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9')
{
if(ch=='-')
w=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9')
s=s*10+(ch-'0'),ch=getchar();
return s*w;
}
long long cal(long long x,long long y)
{
long long sum=0;
sum=(x%y)*(x/y+1)*(x/y+1)+(y-x%y)*(x/y)*(x/y);
return sum;
}
void write(long long s)
{
if(s>9)
write(s/10);
putchar(s%10+'0');
}
int main()
{
freopen("attend.in","r",stdin);
freopen("attend.out","w",stdout);
n=read(),m=read();
for(int i=1;i<=n;++i)
a[i]=read();
for(int i=1;i<=n;++i)
{
int x=read();
a[i]=abs(a[i]-x);
if(a[i])
p.push((node){a[i],1,a[i]*a[i]-cal(a[i],2)}),ans+=a[i]*a[i];
}
if(p.empty())
{
printf("0");
return 0;
}
if(m<p.size())
{
printf("-1");
return 0;
}
m-=p.size();
for(int i=1;i<=m;++i)
{
node k=p.top();
p.pop();
ans-=k.val;
p.push((node){k.x,k.l+1,cal(k.x,k.l+1)-cal(k.x,k.l+2)});
}
ans=ans%mod;
write(ans);
return 0;
}