【10.20 牛客普及(二)】 涨薪 题解
题目
公司中总共有 n n n 个人,其中第 i i i 个人的初始工资为 a i a i ai。公司根据每个人的绩效(工作表现)来评定每个人的涨薪幅度。每年有 x x x 个人绩效为 A A A,工资可以变为原来的 3 倍; y y y 个人绩效为 B B B,工资可以变为原来的 2 倍,其余人绩效为 C C C,工资不变,连续两年绩效为 C C C 会被开除。(保证 x x x+ y y y≤ n n n)
假如公司没有一直招聘新员工,请问 m m m 年后,公司需要给所有在职员工支付的工资总和最多为多少。由于答案可能很大,请输出对 109 + 7取模后的结果。
输入
输入第一行包含四个正整数
n
n
n,
m
m
m,
x
x
x,
y
y
y,意义如题面所示。
接下来一行包含
n
n
n 个正整数,第
i
i
i 个正整数为
a
i
a i
ai 代表第
i
i
i 个人的初始工资。
输出
输出一行一个整数表示 m m m 年后工资总和对 109+7取模后的结果。
样例
input 1
2 1 1 1
5 3
output 1
21
input 2
2 2 0 0
5 2
output 2
0
数据范围
对于 20% 的数据范围,满足
n
n
n≤10,
m
m
m≤10,
a
i
a i
ai≤10
对于 40% 的数据范围,满足
n
n
n≤105,
m
m
m≤10,
a
i
a i
ai≤105
对于另外 20% 的数据范围,满足 满足
n
n
n≤105,m≤10,a i≤105且 x+y=n
对于另外 20% 的数据范围,满足 满足
n
n
n≤105,
m
m
m≤109,
a
i
ai
ai≤105且
x
x
x+
y
y
y=
n
n
n
对于 100% 的数据范围,满足 1≤
n
n
n≤105,1≤
m
m
m≤109,1≤
a
i
ai
ai ≤105
解题思路
按从大到小排序
快速幂求出能涨薪多少倍
前x个乘3快速幂的结果
x
x
x+1~
x
x
x+
y
y
y个乘2快速幂的结果
剩下的相加
如果
m
m
m>1
直接不要
x
x
x+
y
y
y个以后的人
只累加涨薪的人
否则累加所有
代码
#include<algorithm>
#include<iostream>
#include<cstdio>
using namespace std;
const int mo=1000000007;
int n,m,x,y,a[100010];
long long x2,y2,sum,sum2;
bool cmp(int x,int y)
{
return x>y;
}
long long ksm(long long a,long long b,long long m)
{
long long ans=1;
while (b>0)
{
if (b&1)
ans=ans*a%m;
a=a*a%m;
b>>=1;
}
return ans;
}
int main()
{
scanf("%d%d%d%d",&n,&m,&x,&y);
for (int i=1;i<=n;i++)
scanf("%d",&a[i]);
sort(a+1,a+n+1,cmp); //排序
x2=ksm(3,m,mo);
y2=ksm(2,m,mo); //快速幂
for (int i=1;i<=x;i++)
sum=(sum+x2*a[i])%mo;
for (int i=x+1;i<=x+y;i++)
sum=(sum+y2*a[i])%mo; //答案相加
for (int i=x+y+1;i<=n;i++)
sum2=(sum2+a[i])%mo; //不涨薪的
if (m>=2)
printf("%lld",sum); //不要后面的人
else printf("%lld",(sum+sum2)%mo); //全部累加
return 0;
}