问题描述
在蓝桥王国中,有n名士兵,这些士兵需要接受一系列特殊的训练,以提
升他们的战斗技能。对于第i名士兵来说,进行一次训练所需的成本为pi枚金
币,而要想成为顶尖战士,他至少需要进行ci次训练。
为了确保训练的高效性,王国推出了一种组团训练的方案。该方案包含每
位士兵所需的一次训练,且总共只需支付S枚金币(组团训练方案可以多次购
买,即士兵可以进行多次组团训练)。
作为训练指挥官,请你计算出最少需要花费多少金币,才能使得所有的士
兵都成为顶尖战士?
格式输入
输入的第一行包含两个整数n和S,用一个空格分隔,表示士兵的数量和
进行一次组团训练所需的金币数。
接下来的n行,每行包含两个整数pi和ci,用一个空格分隔,表示第i名
士兵进行一次训练的金币成本和要成为顶尖战士所需的训练次数。
格式输出
输出一行包含一个整数,表示使所有士兵成为顶尖战士所需的最少金币数。
样例输入
3 6
5 2
2 4
3 2
样例输出
16
评测用例规模与约定
对于40%的评测用例,1≤n≤10^3,1≤ pi,ci ≤10^5,1≤S ≤10^7。
对于所有评测用例,1≤n≤10^5,1≤ pi,ci ≤10^6,1≤S ≤10^10。
解析
前缀和处理金币和训练次数。然后枚举一起训练从0次到士兵里的最大训练次数,找到最小值。
参考程序
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=100010;
struct Node
{
ll p,c;
bool operator <(const Node &rhs)const
{
return c<rhs.c;
}
}a[N];
ll s1[N],s2[N];
int main()
{
ll n,S;
cin>>n>>S;
for(int i=1;i<=n;i++)
cin>>a[i].p>>a[i].c;
sort(a+1,a+n+1);
for(int i=1;i<=n;i++)
{
s1[i]=s1[i-1]+a[i].p;
s2[i]=s2[i-1]+a[i].p*a[i].c;
}
ll l=a[n].c;
ll ans=1e18;
for(ll i=0,j=0;i<=l;i++)
{
ll cur=S*i;
while(j<n&&a[j+1].c<=i)
j++;
cur+=(s2[n]-s2[j])-(s1[n]-s1[j])*i;
ans=min(ans,cur);
}
cout<<ans;
return 0;
}
赛时写的
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int main(){
ll n,s;cin>>n>>s;
vector<ll>a(n+1);
vector<ll>q(n+1);
ll ans=0,cnt=0,o=1000000010;
for(int i=1;i<=n;i++){cin>>a[i]>>q[i];ans+=a[i];o=min(q[i],o);}
while(1){
if(ans>s){
cnt+=o*s;
for(int i=1;i<=n;i++){if(q[i]>0)q[i]-=o;}
ans=0,o=100000010;
for(int i=1;i<=n;i++){
if(q[i]>0){ans+=a[i];o=min(q[i],o);}
}
}
else{
for(int i=1;i<=n;i++)cnt+=a[i]*q[i];
cout<<cnt;break;
}
}
return 0;
}
难度等级
⭐️⭐️⭐️(1~10星)
以个人刷题整理为目的,如若侵权,请联系删除~