首先假设 n < m n<m n<m,然后不难知道分的每堆口罩的最大数量不能超过 n n n
观察样例发现最优的分法似乎需要先分出 n n n个 n n n,再仔细思考一下,如果是 4 8 4~~8 4 8这组数据,显然需要分为 8 8 8组 4 4 4,这样也满足了 4 4 4组 8 8 8
然后得出我们在分出 ( m / n ) ∗ n (m/n)*n (m/n)∗n组 n n n之后,然后考虑满足有 n n n组 m m m个口罩,那么下面需要分的是 n n n堆 m % n m\%n m%n口罩,现在已经不难看出,这是一个递归的程序,递归的边界是 n = = 1 n==1 n==1时直接分每堆 1 1 1个口罩
为什么不需要考虑这样写能否分为 m m m堆 n n n个口罩,首先已经有了 n n n堆 n n n个口罩,第一次递归的是 d f s ( m % n , n ) dfs(m\%n,n) dfs(m%n,n),也就是下次分的是按照满足最大为 n n n的情况去分,这样剩下的堆凑出的一定能满足 m − n m-n m−n堆 n n n
这个推理过程和 g c d gcd gcd有异曲同工之妙
#include <bits/stdc++.h>
#include <unordered_map>
#include <unordered_set>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define ins insert
#define Vector Point
#define lowbit(x) (x&(-x))
#define mkp(x,y) make_pair(x,y)
#define mem(a,x) memset(a,x,sizeof a);
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef pair<double,double> pdd;
const double eps=1e-8;
const double pi=acos(-1.0);
const int inf=0x3f3f3f3f;
const double dinf=1e300;
const ll INF=1e18;
const int Mod=1e9+7;
const int maxn=2e5+10;
vector<int> ans;
void dfs(int n,int m){
if(n==0) return;
if(n==1){
for(int i=0;i<m;i++) ans.push_back(1);
return;
}
for(int i=0;i<(m/n)*n;i++) ans.push_back(n);
dfs(m%n,n);
}
int main(){
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
ios_base::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int t,n,m;
cin>>t;
while(t--){
cin>>n>>m;
ans.clear();
if(n>m) swap(n,m);
dfs(n,m);
sort(ans.begin(),ans.end(),greater<int>());
cout<<ans.size()<<"\n";
for(auto i: ans) cout<<i<<" ";
cout<<"\n";
}
return 0;
}