【简】题解 AWSL090429 【噪音】
因为每次加上一头奶牛 是什么不重要
牛棚之间贡献除清空操作外无影响
就只要考虑 每个牛棚清空分x次 的贡献
x之和为k 求贡献和最小
一个牛棚清空x次 显然平均清空贡献最小 再用等差数列的公式求
之和就是裸的dp
#include<bits/stdc++.h> using namespace std; #define ll long long #define C getchar()-48 inline ll read() { ll s=0,r=1; char c=C; for(;c<0||c>9;c=C) if(c==-3) r=-1; for(;c>=0&&c<=9;c=C) s=(s<<3)+(s<<1)+c; return s*r; } const ll N=1e6+10,inf=1e9+10; ll n,m,top; ll p[N]; ll gs[N]; ll dp[110][510]; inline ll js(ll w,ll k) { ll v=gs[w];k++; ll bs=v/k; ll duo=v-bs*k; return duo*(1+bs+1)*(bs+1)/2+(k-duo)*(1+bs)*bs/2; } int main() { freopen("noise.in","r",stdin); freopen("noise.out","w",stdout); n=read(),m=read(),top=read(); for(ll i=1;i<=n;i++) p[i]=read(),gs[p[i]]++; for(ll i=1;i<=m;i++) for(ll j=0;j<=top;j++) dp[i][j]=inf; for(ll i=1;i<=m;i++) for(ll k=0;k<=top;k++) for(ll del=0;del<=k;del++) { dp[i][k]=min(dp[i][k],dp[i-1][k-del]+js(i,del)); } cout<<dp[m][top]; return 0; }