ABC150 E - Change a Little Bit
問題のリンク
考察
こういう問題はそれぞれの要素が合計何回足されるかを調べれば良さそう。
コストの和を最小にするためには、Si Ti を満たすようなi のうち、c[i] が小さい順に変更していくのが最適であるとすぐにわかる。
さて、i 番目の要素が異なるとする (Si Ti )。このとき、Sj 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] * * (k + 1) * となる。i 番目の要素が異なるパターンは2 通りなので、さらに2 をかける。
このとき、c[l] < c[i] を満たすようなl については、何を選んでも良いので、さらに をかける。
x はc をソートしておけば、インデックスから簡単に求まるので、c を降順にソートしたうえで、
wolframalphaによると、 (j + 1) * * (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; }