【简】题解 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;
}
posted @ 2019-04-29 09:01  1436177712  阅读(111)  评论(0编辑  收藏  举报