题意:
有n*m个口罩,要求分成最小数目的盒子,使得能组成m组,每组n个口罩。且可以组成n组,每组m个口罩。且最后盒子大小组成的序列字典序最大。
思路:
不妨设
,
则我们要满足分成
组,每组m个,则每个盒子至多为
,为了保证字典序最大且块最少,当前盒子的大小能为m就为m。
考虑医院数量为m,则分成m组每组n个。
每个医院可以分配一个装着m个的口罩的盒子,则每个医院还需要n-m个口罩,那么还需要能将剩下的口罩分成
组,每组
个口罩。
再考虑医院数量为n,则分成n组每组m个,则按照之前分发可以有 个医院满足条件,剩下 个医院没有分到口罩。则还需要分成 组,每组分 个口罩。
所以接下来的问题就可以变成 分成n-m组每组m个,且分成m组每组n-m个的子问题了,和原问题等价,类似GCD的辗转相除,递归解决就好了。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#include <iostream>
#include <map>
#include <string>
using namespace std;
typedef long long ll;
const int mod = 1e9 + 7;
const int maxn = 5000 + 7;
vector<int>vec;
int dfs(int n,int m) {
if(n < m) swap(n,m);
if(m == 0) return 0;
int res = m;
for(int i = 1;i <= m;i++) vec.push_back(m);
res += dfs(m,n - m);
return res;
}
int main() {
int T;scanf("%d",&T);
while(T--) {
int n,m;scanf("%d%d",&n,&m);
if(n == m) {
printf("%d\n",n);
for(int i = 1;i <= n;i++) {
printf("%d ",n);
}
printf("\n");
continue;
}
vec.clear();
int ans = dfs(n,m);
printf("%d\n",ans);
for(int i = 0;i < vec.size();i++) {
printf("%d ",vec[i]);
}
printf("\n");
}
return 0;
}