题目描述
小N最近迷上了购物每天都让小A和小T陪她逛街拿东西。
最近商店出了这样的一个活动:买东西送积分,就是买一件物品,送当前物品的积分ci*当前的倍率,初始倍率是1;当倍率是i的时候,如果你买的物品等于ti个,那么倍率将加1.最多积分的人可以得到超限量版的圆神手办。
小N十分喜欢这个手办但是她又有自己的购物计划,于是她想在这个计划下尽量提高自己的积分。
她有n种东西要买,其中第i种物品她要买ki个,每个可以得到ci的积分。请告诉她积分最多能得到多少吧。
输入
第一行有一个整数n表示要买的种类。
接下来n行每行2个整数ki,ci表示数量和积分
接下来一行有一个正整数t表示奖励的倍数
接下来一行有t个递增的整数ti表示买了ti个物品之后以后买的物品得到的积分倍率将是(i+1)
输出
一个整数,表示小N能得到的最多积分
样例输入
1
5 3
2
3 6
样例输出
21
提示
【样例解释】
前3个物品得到的积分是3*3*1=9,后面2个物品的积分是3*2*2=12
【数据范围】
60%的数据n<=10,sigma(ki)<=1000000
100%的数据n<=100,t<=100,ki<=10^9,0<=ci<=1000,ti<=10^12
想法
- 简单的排序题
算法
- 见代码
代码
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cstring>
#include <string>
#include <cmath>
#define MAXN 105
using namespace std;
typedef long long ll;
int n,m,p=1,q=1,bl=1;
ll t[MAXN],ans,cnt,temp,sum;
struct Node
{
ll k,c;
}g[MAXN];
inline bool cmp(Node x,Node y)
{
return x.c<y.c;
}
int main()
{
//freopen("easy.in","r",stdin);
//freopen("easy.out","w",stdout);
scanf("%d",&n);
for (int i=1;i<=n;i++)
scanf("%lld%lld",&g[i].k,&g[i].c),sum+=g[i].k;
scanf("%d",&m);
for (int i=1;i<=m;i++)
scanf("%lld",&t[i]);
for (int i=2;i<=m;i++)
for (int j=1;j<i;j++)
t[i]-=t[j];
sort(g+1,g+1+n,cmp);
while(cnt<sum)
{
if(t[p]<g[q].k)
{
ans+=t[p]*g[q].c*bl;
g[q].k-=t[p];
bl++;
cnt+=t[p];
p++;
}
else
{
ans+=g[q].k*g[q].c*bl;
t[p]-=g[q].k;
cnt+=g[q].k;
q++;
}
if(p>m)
{
for (int i=q;i<=n;i++)
ans+=g[i].c*g[i].k*bl;
cnt=sum;
}
//cout<<q<<" "<<ans<<endl;
}
cout<<ans<<endl;
return 0;
}