题目链接
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; }