Description
众所周知,小C是个宅男,所以他的每天的食物要靠外卖来解决。小C现在有M元钱,他想知道这些钱他最多可以吃多少天。
餐厅提供N种食物,每种食物有两个属性,单价Pi和保质期Si,表示小C需要花Pi元才能买到足够一天吃的这种食物,并且需要在送到Si天内吃完,否则食物会变质,就不能吃了,若Si为0则意味着必须在送到当天吃完。另外,每次送餐需要额外F元送餐费。
Input
每个测试点包含多组测试数据;
每个测试数据第一行三个整数M,F,N,如题目描述中所述;
以下N行,每行两个整数,分别表示Pi和Si。
Output
对于每个测试数据输出一行,表示最多可以吃的天数。
Sample Input
32 5 2
5 0
10 2
10 10 1
10 10
10 1 1
1 5
Sample Output
3
0
8
HINT
【数据规模及约定】
对于40%的数据,M,Si <= 2*10^6;
对于100%的数据,M, Si<= 10^18,1 ≤ T ≤ 50,1 ≤ F ≤ M,1 ≤ N ≤ 200,1 ≤ Pi ≤ M。
题解
首先删去没用的食品(保质期短还贵的),得到保质期短的便宜,保质期长的贵。
三分购买几次,贪心地从保质期短的开始买。
代码
#include<bits/stdc++.h>
#define ll long long
#define inf 1000000000
#define pa pair<ll,ll>
using namespace std;
const int mod=1000000007;
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
struct node{ll p,s;}a[205],b[205];
ll n,f,m;
pa ans;
bool cmp(node a,node b)
{
return (a.s==b.s)?a.p<b.p:a.s<b.s;
}
pa judge(ll mid)
{
ll rest=m-f*mid,day=0,now=0;
for (int i=1;i<=n;i++)
{
if (b[i].s>=day)
{
ll j=min(rest/b[i].p/mid,b[i].s-day+1);
day+=j;now+=mid*j;rest-=b[i].p*j*mid;
}
if (b[i].s>=day)
{
ll j=min(rest/b[i].p,mid);
now+=j;day++;rest-=b[i].p*j;
}
}
return make_pair(now,rest);
}
int main()
{
while (scanf("%lld%lld%lld",&m,&f,&n)!=EOF)
{
for (int i=1;i<=n;i++) scanf("%lld%lld",&a[i].p,&a[i].s);
sort(a+1,a+n+1,cmp);int _n=0;
for (int i=1;i<=n;i++)
{
while (_n!=0&&a[i].p<=b[_n].p) _n--;
b[++_n]=a[i];
}
n=_n;
ll l=1,r=m/(f+b[1].p);ans=make_pair(0,0);
while (l<=r)
{
ll m1=l+(r-l)/3,m2=r-(r-l)/3;pa s1,s2;
if ((s1=judge(m1))>(s2=judge(m2)))
{
ans=max(ans,s1);
r=m2-1;
}
else
{
ans=max(ans,s2);
l=m1+1;
}
}
printf("%lld\n",ans.first);
}
return 0;
}