codeforces 1428E. Carrots for Rabbits(貪心(非常優秀的貪心題),結構體過載運算子)

I_have_a_world發表於2020-10-18

題目連結:https://codeforces.ml/contest/1428/problem/E

題意:給定n個數,要求將這些數拆分為k個數,是這些數的平方和最小。

題解:結構體,一開始想到的是每次分最大的數,平分。然鵝,1 3 10000.是分成3333 3333 3334顯然更好。

換一換貪心思路。每一個數多拆分一種就有特定的平方和減小值,如10分成3:3 3 4,分成4 份:2 2 3 3減小值為8.

一個數分為k種,有特定的最小平方和(平分,見gv函式)。然後每一次只需要關注減小值最大的數。

程式碼:

#include <bits/stdc++.h>

#define ll long long
#define pi acos(-1)
#define pb push_back
#define mst(a, i) memset(a, i, sizeof(a))
#define pll pair<ll, ll>
#define fi first
#define se second
#define dbg(x) cout << #x << "===" << x << endl
using namespace std;
template <class T> void read(T &x) {
    T res = 0, f = 1;
    char c = getchar();
    while (!isdigit(c)) {
        if (c == '-') f = -1;
        c = getchar();
    }
    while (isdigit(c)) {
        res = (res << 3) + (res << 1) + c - '0';
        c = getchar();
    }
    x = res * f;
}
void print(ll x) {
    if (x < 0) {
        putchar('-');
        x = -x;
    }
    if (x > 9) print(x / 10);
    putchar(x % 10 + '0');
}
const ll maxn = 1e5 + 10;
const ll mod = 1e9 + 7;


ll n,k,x;
struct node{
    ll a,b,c;
    bool operator < (const node &b)const{
        return a<b.a;
    }
};
// ll gcd(ll a,ll b){return (b==0)?a:gcd(b,a%b);}
// ll qpow(ll a,ll p,ll mod){ll
// ans=1;a=a%mod;while(p){if(p&1)ans=(ans*a)%mod;p>>=1;a=(a*a)%mod;}return ans;}
// ll vis[maxn],prime[maxn],x=0;
// void oulasai(ll n){for(ll i=2;i<=n;i++){if(!vis[i]) prime[x++]=i;for(int
// j=0;j<x;j++){if(i*prime[j]>n) break;vis[i*prime[j]]=true;if(i%prime[j]==0)
// break;}}}
/*?組合數
ll fac[maxn],re[maxn],inv[maxn];
//void init(ll n){inv[0]=inv[1]=fac[0]=fac[1]=re[0]=re[1]=1;for(ll
i=2;i<=n;i++){fac[i]=fac[i-1]*i%mod;inv[i]=(mod-mod/i)*inv[mod%i]%mod;re[i]=re[i-1]*inv[i]%mod;}}
ll C(ll n,ll m){return fac[n]%mod*re[m]%mod*re[n-m]%mod;}
*/
// ll inv(ll a){return a==1?1:(ll)(mod-mod/a)*inv(mod%a)%mod;}
// void exgcd(ll a,ll b){if(b==0){x=1,y=0;g=a;return ;}exgcd(b,a%b);ll
// tmp=y;y=x-(a/b)*y;x=tmp;return ;}
/*
ll fa[maxn],dep[maxn],
ll find(ll x){ll r=x,p;while(r!=fa[r]) r=fa[r];while(x!=r)
p=fa[x],fa[x]=r,x=p;return r;} void merge(ll x,ll y){ll
fx=find(x),fy=find(y);if(dep[fx]<dep[fy])
fa[fx]=fy;else{fa[fy]=fx;if(dep[fx]==dep[fy]) dep[fx]++;}return ;}
*/

ll gv(ll a,ll x){//?a被切成x份 
    ll m=a/x,t=a%x;
    return t*(m+1)*(m+1)+(x-t)*m*m;
}
priority_queue<node> q;
int main() {
    ll _s = 1;
    //read(_s);
    for (ll _ = 1; _ <= _s; _++) {
        read(n),read(k);
        ll ans=0;
        for(ll i=1;i<=n;i++){
            read(x);
            q.push({gv(x,1)-gv(x,2),x,2});
            ans+=x*x;
        }
        for(ll i=1;i<=k-n;i++){
            node now=q.top();q.pop();
            ll a=now.a,b=now.b,c=now.c;
            ans-=a;
            q.push({gv(b,c)-gv(b,c+1),b,c+1});
        }
        cout<<ans<<endl;
    }
    return 0;
}
//不正確,不輕易執行 
/*
input:::
output:::

*/

 

相關文章