現代の量子力学

主に精進の様子を記録する日記帳です

ABC150 E - Change a Little Bit

問題のリンク

E - Change a Little Bit

考察

こういう問題はそれぞれの要素が合計何回足されるかを調べれば良さそう。

コストの和を最小にするためには、Si  \neq Ti を満たすようなi のうち、c[i] が小さい順に変更していくのが最適であるとすぐにわかる。

さて、i 番目の要素が異なるとする (Si  \neq Ti )。このとき、Sj  \neq Tj を満たすj のうちc[i] < c[j] を満たすj があるk 個であるとする。すると、そのk 個については、i 番目の要素を変更した後に変更することになるので、このときに結果に追加される値は、c[i] * (k + 1) となる。

ここで、上のようなj がk 個であるならば、どの要素がそのk 個に入っているかは関係ないのでまとめることができて、c[i] < c[l] を満たすようなl がx 個ある場合、c[i] *  2 ^ x * (k + 1) *  _ {x} C _ {k} となる。i 番目の要素が異なるパターンは2 通りなので、さらに2 をかける。

このとき、c[l] < c[i] を満たすようなl については、何を選んでも良いので、さらに 4 ^ {n - x - 1} をかける。

x はc をソートしておけば、インデックスから簡単に求まるので、c を降順にソートしたうえで、

 \sum _ {i = 0} ^ {n-1} c[i] *  4 ^ {n - i - 1} *  2 ^ {i+1} *  \sum _ {j=0} ^ i (j + 1) *  _ i C _ j

wolframalphaによると、  \sum _ {j=0} ^ i (j + 1) *  _ i C _ {j} = 2 ^ {i-1} * (i+2) なので、結局、

 \sum _ {i = 0} ^ {n-1} c[i] *  4 ^ {n - i - 1} *  2 ^ {2 * i} * (i+2)

で求めることができる。(あれ、4の冪乗だけで良い?)
以下実装

#include <iostream>
#include <algorithm>
#include <vector>
#define rep(i,n) for(int i=0;i<n;++i)
#define rep1(i,n) for(int i=1;i<=n;++i)
using namespace std;
template<class T>bool chmax(T &a, const T &b) { if(a < b){ a = b; return 1; } return 0; }
template<class T>bool chmin(T &a, const T &b) { if(a > b){ a = b; return 1; } return 0; }
typedef long long ll;
const ll MOD=1e+9+7;
struct mint{
  ll x;
  mint(ll x=0):x(x%MOD){}
  mint& operator+=(const mint a){
    if((x+=a.x)>=MOD) x-=MOD;
    return *this;
  }
  mint& operator-=(const mint a){
    if((x += MOD-a.x)>=MOD) x-=MOD;
    return *this;
  }
  mint& operator*=(const mint a){
    (x*=a.x)%=MOD;
    return *this;
  }
  mint operator+(const mint a) const{
    mint res(*this);
    return res+=a;
  }
  mint operator-(const mint a) const{
    mint res(*this);
    return res-=a;
  }
  mint operator*(const mint a) const{
    mint res(*this);
    return res*=a;
  }
  mint pow(ll t) const{
    if(!t) return 1;
    mint a = pow(t>>1);
    a*=a;
    if(t&1) a*=*this;
    return a;
  }
  
  //for prime mod
  mint inv() const{
    return pow(MOD-2);
  }
  mint& operator/=(const mint a){
    return (*this) *= a.inv();
  }
  mint operator/(const mint a) const{
    mint res(*this);
    return res/=a;
  }
};

const int NMAX=200010; // we can calculate nCk until n is equal to NMAX
mint fact[NMAX],infac[NMAX];
void Make_Fact(){
  fact[0]=fact[1]=1;
  for(int i=2;i<=NMAX-1;++i){
    fact[i]=fact[i-1]*(mint)i;
  }
}
void Make_InvFact(){
  infac[0]=infac[1]=1;
  for(int i=2;i<=NMAX-1;++i){
    infac[i]=infac[i-1]/(mint)i;   
  }
}
mint Comb(int n,int k){
  if(n<0||k<0||n-k<0) return 0;
  return fact[n]*infac[k]*infac[n-k];
}

mint pow2[400010];

int main()
{
  int n; cin >> n;
  vector<int> c(n);
  rep(i,n) cin >> c[i];

  sort(c.begin(), c.end());
  reverse(c.begin(), c.end());
  
  pow2[0].x = 1;
  rep(i,400000) {
    pow2[i+1] = pow2[i]*(mint)2;
  }

  mint res;
  rep(i,n) {
    res += (mint)c[i] * pow2[2*(n-i-1)] * pow2[2*i] * (mint)(i+2);
  }
  cout << res.x << "\n";
  
  return 0;
}