有 \(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;
}