Codeforces Round 218(Div.2 Only) C. Hamburgers

問題

ハンバーガーのレシピがあります。要するに1つのハンバーガーを作るのに
・パン
・ソーセージ
・チーズ
の3つの材料がそれぞれ何個ずつ要るかが文字列sとして与えられます。
手持ちの3つの材料の数ns,ns,ncと、
3つの材料を買い足す場合の単価pb,ps,pc、
そして所持金rが与えられます。

所持金の範囲でいくらでも材料を買い足せるとして、最大何個のハンバーガーを作れるでしょう?

制約
1≦ns,ns,nc≦100
1≦ps,ps,pc≦100
1≦r≦10^12


解法

作れるハンバーガーの数は、
たとえばパン1つだけ、というレシピでns=100, ps=1, r=10^12のときが最高で10^12+100です。

ということで高々こんなものであれば二分探索で「n個のハンバーガーを作ることはできるか?」を見ていくことで答えにたどり着けます。
これはn個作るのに材料がいくら足りないからいくら掛かる、ということを計算してrと比較すれば求まります。

自分は二分探索するのが面倒だったので、
「最初の手持ちで作れるハンバーガーは高々100個」という性質を使って、
101個以上作るときは全部買い足し食材になるので100作った時点で残ってる所持金をハンバーガー材料の値段で割って計算し、
100個以下しか作れないときは線形探索していました。

プログラム

#include<iostream>
#include <fstream>
#include <stdio.h>
#include <stdlib.h>
#define _USE_MATH_DEFINES
#include <math.h>
#include<string>
#include<vector>
#include<cmath>
#include<stack>
#include<queue>
#include<sstream>
#include<algorithm>
#include<map>
#include<complex>
#include<ctime>
#include<set>
using namespace std;


#define li			long long int
#define rep(i,to)	for(li i=0;i<((li)(to));i++)
#define repp(i,start,to)	for(li i=(li)(start);i<((li)(to));i++)
#define pb			push_back
#define sz(v)		((li)(v).size())
#define bgn(v)		((v).begin())
#define eend(v)		((v).end())
#define allof(v)	(v).begin(), (v).end()
#define dodp(v,n)		memset(v,(li)n,sizeof(v))
#define bit(n)		(1ll<<(li)(n))
#define mp(a,b)		make_pair(a,b)
#define rin	rep(i,n)
#define EPS 1e-10
#define ETOL 1e-8
#define MOD 100000000
#define F first
#define S second
#define p2(a,b)		cout<<a<<"\t"<<b<<endl
#define p3(a,b,c)		cout<<a<<"\t"<<b<<"\t"<<c<<endl

#define INFF 1000000000000

li kos(li kosu, li need){
	if(need==0)return INFF;
	return kosu/need;
}

	li b,s,c;
	li pb, ps, pc;
	li hb=0, hs=0, hc=0;
	li r;

bool ok(li n){
	li price=0;
	price+=max(0ll, (hb*n-b)*pb);
	price+=max(0ll, (hs*n-s)*ps);
	price+=max(0ll, (hc*n-c)*pc);
	return r-price>=0;
}

int main(){
	string recipe;

	cin>>recipe;
	cin>>b>>s>>c;
	cin>>pb>>ps>>pc;
	cin>>r;

	rep(i,sz(recipe)){
		hb+=(recipe[i]=='B');
		hs+=(recipe[i]=='S');
		hc+=(recipe[i]=='C');
	}

	li res=0;
	li sb,ss,sc;
	li ma=101;

	li ccc=0;
	ccc+=max((ma*hb-b)*pb,0ll);
	ccc+=max((ma*hc-c)*pc,0ll);
	ccc+=max((ma*hs-s)*ps,0ll);
	if(ccc<=r){
		res=ma;
		r-=ccc;
		res+=r/(hb*pb+hs*ps+hc*pc);
		cout<<res<<endl;
		return 0;
	}

	res=0;
	repp(i,1,101){
		if(ok(i)){
			res=i;
		}
		else break;
	}
	cout<<res<<endl;

	return 0;
}