(1)题目大意
给你一些工具龙,和孵蛋的一些要求,现在问你给你的这些工具龙最多能使蛋到多少级。
(2)解题思路(二分+贪心)
我们考虑二分答案,check的时候尽量先把工具龙分配给比他大的那些孵蛋要求,因此我们check的时候尽量先给大的,然后贪心的从大到小分配剩下的工具龙,注意过程中可能爆longlong,因此要开int128去跑。
(3)代码实现
#include "bits/stdc++.h"
#define rep(i,z,n) for(int i = z;i <= n; i++)
#define per(i,n,z) for(int i = n;i >= z; i--)
#define ll long long
#define db double
#define PII pair<int,int>
#define fi first
#define se second
#define vi vector<int>
#define yes cout << "YES" << endl;
#define no cout << "NO" << endl;
using namespace std;
const int N = 1e5 + 10;
using i128 = __int128;
ll a[N],b[N];
i128 c[N];
int n,m;
bool check(ll mid)
{
for(int i = 1;i <= n;i ++) c[i] = a[i] * (i128)mid;
for(int i = m;i >= 1;i --) {
ll dragons = b[i];
for(int j = 1;j <= n;j ++) {
i128 cnt = min(c[j] / (1 << (i - 1)),(i128)dragons);
c[j] -= cnt * (1 << i - 1);
dragons -= cnt;
}
//剪枝
if(!dragons) continue;
if(dragons >= n) return true;
sort(c + 1,c + 1 + n,[](i128 &p1,i128 &p2){
return p1 > p2;
});
for(int j = 1;j <= dragons;j++) c[j] = 0;
}
for(int i = 1;i <= n;i++) if(c[i]) return false;
return true;
}
void solve()
{
cin >> n >> m;
for(int i = 1;i <= n;i ++) cin >> a[i];
for(int i = 1;i <= m;i ++) cin >> b[i];
ll l = 0,r = 1e18;
while(l <= r) {
ll mid = (l + r) >> 1;
if(check(mid)) l = mid + 1;
else r = mid - 1;
}
cout << l - 1 << endl;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
int T = 1;
cin >> T;
while(T --) solve();
return 0;
}