题目链接

https://ac.nowcoder.com/acm/contest/7606/C

解题思路

开始看到这个题,感觉好难啊,到底怎么贪心啊,变的这么多。
结果发现居然做出来了,就是少了个细节少了10分。
对于每年的加薪,我们有两种选择,可以一群人加薪,另一群不加,下一年再给上一次加薪的继续加薪,给不加薪的继续不加,让他们淘汰,这样最后第m年(m>2)肯定就没有这些被淘汰的人对答案的贡献了;另外,若对去年没加薪的加薪,对去年加薪的不加薪,把人留住了,这样最后第m年(m>2)所有人(不一定是所有人都能留下)都对答案有贡献了。
到底哪个更好?
首先,我们很容易能想到的是肯定要对本来薪水就高的进行翻倍处理,这样才能效果最明显吧。

我们不严谨地证明一下:
假设就俩人,初始薪水分别为x1和x2且x1>x2,规定只能有一个评定为A,一个评定为C。

方案一:淘汰一人:
第一年在线员工支付的总和:3*x1+x2
第二年在线员工支付的总和:9*x1,x2被淘汰了

方案二:无人被淘汰:
第一年在线员工支付的总和:3*x1+x2
第二年在线员工支付的总和:3*x1+3*x2

假设方案二的第二年的总和比方案一的大:3*x1+3*x2>9*x1
已知中x1>x2
联立求解,最后无解,说明我们假设方案二的第二年的总和比方案一的大是错误的,那么,方案一优于方案二。

不严谨地说明还是让薪水高的一直翻倍对最终答案影响大。

所以我们将所有人排序,大的翻3倍,其次的翻2倍,剩下的淘汰(对答案无影响)。
但是注意一点,当m<2的时候,是不存在有人被淘汰的,所以应该把那些没有翻倍的人的薪水也加上。

AC代码

#include<bits/stdc++.h>
#include<iostream>
#define ll long long
using namespace std;
const int mod=1e9+7;
const int N=1e5+100;
bool cmp(ll x,ll y){
    return x>y;
}
ll KSM(ll x,ll p){
    ll ans=1;
    while(p){
        if(p&1LL) ans=ans*x%mod;
        x=x*x%mod;
        p>>=1;
    }
    return ans;
}
int main(){
    ll n,m,x,y,a[N],ans=0,tmp;
    /*
    //文件输入 
    ifstream fin("C:/Users/秃头小白/Desktop/1.普及组/普及T3/tiaoxin.in");
    fin>>n>>m>>x>>y;
    for(ll i=1;i<=n;i++) fin>>tmp,a[i]=tmp%mod;
    */
    cin>>n>>m>>x>>y;
    for(int i=1;i<=n;i++) cin>>tmp,a[i]=tmp%mod;
    sort(a+1,a+n+1,cmp);
    ll x3=KSM(3,m),x2=KSM(2,m);

    for(ll i=1;i<=n;i++){
        if(i<=x) ans=(ans+x3*a[i]%mod)%mod;
        else if(i<=x+y) ans=(ans+x2*a[i]%mod)%mod;
        else if(m<2) ans=(ans+a[i])%mod;//易漏
    }
    cout<<ans<<endl;    
}