题意:给定$m$种糖果,共$n$个。再给定大小为$m$个数组$l[]$,表示:如果要选第$i$种糖果至少要选$l[i]$个。再给定$n$组数据分别表示第$i$个糖果的价值和类型。最后定义一个标准$S/C$,其中$S$表示所选糖果的价值总和,$C$表示所选种类中个数最多的数量(比如第1种选了2个,第2种选了1个,第3种选了4个,最后$C=4$)。
思路:枚举分母,计算在当前分母下最多可以取到糖果的价值总和。
做法:将糖果按类型分组,为了使取得在数量最少的情况下价值最大,将糖果按价值逆序排序,然后将糖果按照顺序分别放入对应数量的分组中,若当前糖果的次序未达到所要求的最小数量$a[i]$,应该归到$a[i]$中。最后枚举分母,然后将分子不断累加,取$S/C$的最大值输出即可。
#include <iostream>
#include <cstring>
#include <set>
#include <map>
#include <vector>
#include <queue>
#include <stack>
#include <algorithm>
#include <cmath>
#include <unordered_map>
#define bug1(g) cout<<"test: "<<g<<endl
#define bug2(g , i) cout<<"test: "<<g<<" "<<i<<endl
#define bug3(g , i , k) cout<<"test: "<<g<<" "<<i<<" "<<k<<endl
#define bug4(a , g , i , k) cout<<"test: "<<a<<" "<<g<<" "<<i<<" "<<k<<endl
#define INF 0x3f3f3f3f
#define fi first
#define se second
#define met(a , b) memset(a , b , sizeof a);
#define pb push_back
using namespace std;
typedef long long LL ;
typedef pair<int , int> PII;
const int N = 1000010;
int l[N];
vector<int> vec[N];
vector<int> sweet[N];
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<<1)+(x<<3)+(ch^48);
ch=getchar();
}
return x*f;
}
void solve()
{
int n , m;
cin >> n >> m;
for(int i = 1 ; i <= m ; i++) cin >> l[i];
for(int i = 0 ; i < n ; i++)
{
int x , y;
x = read() , y = read();
sweet[y].pb(x);
}
int maxv = 0;
for(int i = 1 ; i <= m ; i++)
if(sweet[i].size() >= l[i])
{
maxv = max(maxv , (int)sweet[i].size());
LL tmp = 0;
sort(sweet[i].begin() , sweet[i].end() , greater<int>());
for(int j = 0 ; j < sweet[i].size() ; j++) vec[max(j + 1 , l[i])].pb(sweet[i][j]);
sweet[i].clear();
}
LL up = 0 , down = 1 , s = 0;
for(int i = 1 ; i <= maxv ; i++)
{
LL t = i;
for(int j = 0 ; j < vec[i].size() ; j++)
s += vec[i][j];
vec[i].clear();
if(s * down > t * up) up = s , down = t;
}
LL d = __gcd(up , down);
cout << up / d << '/' << down / d << endl;
}
int main()
{
int T = 1;
cin >> T;
for(int turn = 1 ; turn <= T ; turn++)
solve();
}