[WC2025] 猫粮
有 \(n\) 只猫猫,每只猫猫都要吃至少 \(m\) 克猫粮才能吃饱。
有 \(n\) 袋优质猫粮,第 \(i\) 袋优质猫粮的克数为 \(a_i\)。你还有 \(n\) 袋普通猫粮,第 \(i\) 袋普通猫粮的克数为 \(b_i\)。
优质猫粮的味道很好,当你打开一袋优质猫粮后,所有没有吃饱的猫猫都会来抢,其中的任何一只猫猫都可能抢走这袋猫粮。普通猫粮味道一般,当你喂给一只猫猫后,不会有别的猫猫来抢。
你需要判断是否存在一种方法,可以喂饱所有的猫猫。
\(T \leq 50\) 组数据,\(1 \leq n \leq 40000\),\(2 \leq m \leq 10^5\)。保证 \(1 \leq a_i,b_i \leq m-1\),且 \(\sum\limits_{i=1}^{n} a_i + \sum\limits_{i=1}^{n} b_i = nm\)。
由题目的数据范围限制,可知在喂饱所有的猫猫的情况下,所有猫粮不能产生浪费。同时一只猫猫吃一袋猫粮一定不够,我们可以得到结论:每只猫猫都要吃恰好两袋猫粮。
考虑将 \(a_i+b_j=m\) 的猫粮配对,假设配成的对数为 \(x\),接下来分类讨论:
-
\(x=n\),此时我们只需要先打开一袋优质猫粮,当一只猫猫吃了这袋猫粮后,把对应的普通猫粮喂给这只猫猫即可。这样一定是有解的。
-
\(x=n-2\),此时我们喂完其他的猫猫后不能使用刚才的策略,考虑使用两袋普通猫粮和两袋优质猫粮分别喂饱两只猫猫。此时要求两袋普通猫粮和两袋优质猫粮的和均为 \(m\)。
-
\(x<n-2\),此时剩下多组未匹配的猫粮,无法使用第一种情况的方法,我们只能先让普通猫粮互相配对。此时一定要求 \(2 \mid n-x\),接下来只需要普通猫粮能配成若干对即可。然后你需要保证优质猫粮互相没有区别,即 \(2 \mid m\) 且剩下每袋优质猫粮都是 \(\dfrac{m}{2}\)。
结束了。
#include<iostream>
#include<cstdio>
using namespace std;
int cnt_a[100010],cnt_b[100010],cnt_tmp_a[100010],cnt_tmp_b[100010];
int main(){
int T;
scanf("%d",&T);
while(T--){
int n,m;
scanf("%d %d",&n,&m);
for(int i=1;i<m;i++){
cnt_a[i]=cnt_b[i]=cnt_tmp_a[i]=cnt_tmp_b[i]=0;
}
for(int i=1;i<=n;i++){
int num;
scanf("%d",&num);
cnt_a[num]++;
}
for(int i=1;i<=n;i++){
int num;
scanf("%d",&num);
cnt_b[m-num]++;
}
int x=0;
for(int i=1;i<m;i++){
x+=min(cnt_a[i],cnt_b[i]);
cnt_tmp_a[i]+=cnt_a[i]-min(cnt_a[i],cnt_b[i]);
cnt_tmp_b[i]+=cnt_b[i]-min(cnt_a[i],cnt_b[i]);
}
if(x==n){
printf("Yes\n");
}
else if(x==n-2){
int sum_a=0,sum_b=0;
for(int i=1;i<m;i++){
for(int j=1;j<=cnt_tmp_a[i];j++){
sum_a+=i;
}
for(int j=1;j<=cnt_tmp_b[i];j++){
sum_b+=i;
}
}
if(sum_a==m && sum_b==m){
printf("Yes\n");
}
else{
printf("No\n");
}
}
else{
bool flag=true;
if((n-x)%2!=0){
flag=false;
}
if(m%2!=0){
flag=false;
}
for(int i=1;i<m;i++){
if(cnt_tmp_b[i]!=cnt_tmp_b[m-i]){
flag=false;
}
}
if(cnt_tmp_a[m/2]!=n-x){
flag=false;
}
if(flag){
printf("Yes\n");
}
else{
printf("No\n");
}
}
}
return 0;
}

浙公网安备 33010602011771号