题目描述
你有 nm 颗糖果。如果有 n 个小朋友来你家,你需要分给他们每人 m 颗糖;如果来的是
m 个小朋友,你就要分给每人 n 颗。
你打算把糖果分装在 k 个盒子里,每个盒子分别放几颗糖由你来决定。分糖果时,盒子是
不能被拆开的。(小朋友们拿到的只能是装着糖果的盒子,而不是散装的糖果)
你希望最小化盒子的数量 k,使得不论来了 n 个还是 m 个小朋友,你都能按照要求给他
们分糖果。
输入格式
第一行包含三个整数 n, m, t。
输出格式
如果 t = 0,你只需输出一个整数,表示最小的 k。
如果 t = 1,你需要在第一行输出一个整数,表示最小的 k;在第二行输出由空格隔开的 k
个整数,按照降序排列,表示每个盒子内的糖果数量。如果有多种方案使得 k 最小,你需要输
出其中字典序最大的。
样例输入 1
3 4 0
样例输出 1
6
样例输入 2
3 4 1
样例输出 2
6
3 3 3 1 1 1
样例解释
如 果 来 了 3 个 小 朋 友, 分 别 给 {3, 1}, {3, 1}, {3, 1}; 如 果 来 了 4 个 小 朋 友, 分 别 给
{3}, {3}, {3}, {1, 1, 1}。
另外,{3, 3, 2, 2, 1, 1} 也是一组使得 k 最小的合法解,但它并不是字典序最大的。
题解:
这个题目,代码十分短,但在考试时候没有发现,当然,考试的时候,想发现构造题和贪心题还有dp题,手玩都特别有好处,所以想不出来还是要手玩一下。
题目本身就是一个更相减损法,递归子问题。
代码:
#include <cstdio> #include <iostream> #include <algorithm> #include <cstring> #include <cmath> #include <iostream> #define MAXN 100 using namespace std; int ans; void dfs2(int n,int m,int num){ if(n==m) {num+=n;ans=num;return;} else{ num+=m; n-=m; if(n<m) swap(n,m); dfs2(n,m,num); } } void dfs1(int n,int m){ if(n==m){ for(int i=1;i<=n;i++) printf("%d ",n); return; } else{ for(int i=1;i<=m;i++) printf("%d ",m); n-=m; if(n<m) swap(n,m); dfs1(n,m); } } int main() { int t,n,m; scanf("%d%d%d",&n,&m,&t); if(n<m) swap(n,m); dfs2(n,m,0); printf("%d ",ans); if(t==1) dfs1(n,m); return 0; }