CF119B Before Exam 题解

题意

分析

由于已经强制配好了 \(q\) 张卡片,那么现在为了让熟练度最大,就将剩下的定理中熟练度最大的 \(\left\lfloor\dfrac{n}{k}\right\rfloor\) 个定理配成一张卡片,此时熟练度的最大值就是这 \(\left\lfloor\dfrac{n}{k}\right\rfloor\) 个定理熟练度的平均数和已配好卡片平均数的最大值。同理,最小熟练度就是剩下定理中熟练度最小的 \(\left\lfloor\dfrac{n}{k}\right\rfloor\) 个定理的平均数和已配好卡片平均数的最小值。

代码

#include <bits/stdc++.h>
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
const int MAXN=107;
inline void qread(){}template<class T1,class ...T2>
inline void qread(T1 &a,T2&... b)
{
	register T1 x=0;register bool f=false;char ch=getchar();
	while(ch<'0') f|=(ch=='-'),ch=getchar();
	while(ch>='0') x=(x*10)+(ch^48),ch=getchar();
	x=(f?-x:x);a=x;qread(b...);
}
template<class T1,class T2>inline T1 qmin(const T1 &x,const T2 &y){return x<y?x:y;}
template<class T1,class T2>inline T1 qmax(const T1 &x,const T2 &y){return x>y?x:y;}
int n,k,q;vector<int>a,c;
int b[MAXN][MAXN];
bitset<MAXN>vis;vector<int>tmp;
int mx,mn=2139062143;
map<vector<int>,bool>mp;
int main()
{
	qread(n,k);int i,j;a.resize(n+1);for(i=1;i<=n;i++) qread(a[i]);qread(q);
	int m=n/k,cnt=0; // cnt表示已配好的卡片数
	for(i=0;i<q;i++) 
	{
		int sum=0;tmp.clear();
		for(j=0;j<m;j++) qread(b[i][j]),vis[b[i][j]]=true,sum+=a[b[i][j]],tmp.push_back(b[i][j]);
		sort(tmp.begin(),tmp.end());if(!mp[tmp]) mp[tmp]=true,cnt++; // 由于前q张可能有重复,所以用map记一下去重
		mx=qmax(mx,sum);mn=qmin(mn,sum);
	}
	for(i=1;i<=n;i++) if(!vis[i]) c.push_back(a[i]); // 剩余的定理的平均数
	int t=0;
	if(c.size()>=m&&k-cnt>0)
	{
		sort(c.begin(),c.end(),greater<int>());for(i=0;i<m;i++) t+=c[i];mx=qmax(mx,t); // 最大值
		t=0;sort(c.begin(),c.end());for(i=0;i<m;i++) t+=c[i];mn=qmin(mn,t); //最小值
	}
	printf("%.10lf %.10lf\n",mn/1.0/m,mx/1.0/m);
	// system("pause");
	return 0;
}
posted @ 2022-02-17 19:48  l_x_y  阅读(28)  评论(0编辑  收藏  举报