题意
分 解 n ∗ m , 使 得 满 足 两 个 条 件 : ( 1 ) 分 解 的 数 中 可 以 组 合 成 n 组 , 每 组 的 值 为 m ( 2 ) 分 解 的 数 中 可 以 组 合 成 m 组 , 每 组 的 值 为 n 分解n*m,使得满足两个条件:\\(1)分解的数中可以组合成n组,每组的值为m\\(2)分解的数中可以组合成m组,每组的值为n 分解n∗m,使得满足两个条件:(1)分解的数中可以组合成n组,每组的值为m(2)分解的数中可以组合成m组,每组的值为n
要 使 得 分 解 的 个 数 少 , 若 相 同 输 出 字 典 序 最 大 的 一 种 方 案 要使得分解的个数少,若相同输出字典序最大的一种方案 要使得分解的个数少,若相同输出字典序最大的一种方案
思路
考 虑 n = = m 情 况 简 单 直 接 输 出 n 个 n 即 可 , 显 然 考虑n==m情况\\简单直接输出n个n即可,显然 考虑n==m情况简单直接输出n个n即可,显然
考 虑 n ! = m 情 况 , 方 便 起 见 , 直 接 令 n < m 思 考 : ( 1 ) m 、 m 、 m 、 . . . 、 m , 共 n 个 考虑n!=m情况,方便起见,直接令n
( 2 ) n 、 n 、 n 、 . . . . 、 n , 共 n 个 (2)n、n、n、....、n,共n个 (2)n、n、n、....、n,共n个
把 ( 1 ) 中 的 每 个 m 都 减 掉 n 可 得 到 m − n 共 n 个 把(1)中的每个m都减掉n可得到m-n共n个 把(1)中的每个m都减掉n可得到m−n共n个
( 3 ) m − n 、 m − n 、 m − n 、 . . . 、 m − n , 共 n 个 (3)m-n、m-n、m-n、...、m-n,共n个 (3)m−n、m−n、m−n、...、m−n,共n个
观 察 ( 1 ) ( 2 ) 与 ( 2 ) ( 3 ) 很 相 似 , 产 生 联 想 , 这 会 不 会 是 动 态 规 划 , 由 一 个 状 态 转 移 另 外 一 个 状 态 呢 ? 观察(1)(2)与(2)(3)很相似,产生联想,这会不会是动态规划,\\由一个状态转移另外一个状态呢? 观察(1)(2)与(2)(3)很相似,产生联想,这会不会是动态规划,由一个状态转移另外一个状态呢?
证明
设 d p ( n , m ) 表 示 分 解 n ∗ m 的 方 案 ( 注 意 n < m ) 设dp(n, m)表示分解n*m的方案(注意n
d p ( n , , m ) 与 d p ( m − n , n ) 关 系 呢 ? dp(n,,m)与dp(m - n, n)关系呢? dp(n,,m)与dp(m−n,n)关系呢?
d p ( n , m ) : 存 在 n 组 m 以 及 m 组 n d p ( m − n , n ) : 存 在 m − n 组 n 以 及 n 组 m − n dp(n, m):存在n组m以及m组n\\dp(m-n, n):存在m-n组n以及n组m-n dp(n,m):存在n组m以及m组ndp(m−n,n):存在m−n组n以及n组m−n
d p ( n , m ) = d p ( m − n , n ) + n 个 n dp(n, m) = dp(m -n, n)+n个n dp(n,m)=dp(m−n,n)+n个n
很显然
m − n 组 n + n 组 n = m 组 n m-n组n+n组n=m组n m−n组n+n组n=m组n
n 组 m − n + n 组 n = n 组 m n组m-n+n组n=n组m n组m−n+n组n=n组m
因 为 d p ( m − n , n ) 是 最 优 状 态 , + n 个 n 显 然 是 最 优 秀 的 转 移 因为dp(m-n,n)是最优状态,+n个n显然是最优秀的转移 因为dp(m−n,n)是最优状态,+n个n显然是最优秀的转移
d p ( ) 初 始 状 态 很 简 单 , 即 d p ( c , c ) 为 c 个 c dp()初始状态很简单,即dp(c,c)为c个c dp()初始状态很简单,即dp(c,c)为c个c
#include
using namespace std;
typedef long long ll;
const int maxn = 1e4 + 10;
int n, m;
vector<int> v;
void dfs(int n, int m){
if(n == 0) return ;
for(int i = 1; i <= n; i++){
v.push_back(n);
}
int res = m - n;
if(res > n) swap(res, n);
dfs(res, n);
}
int main(){
int t;
scanf("%d", &t);
while(t--){
v.clear();
scanf("%d%d", &n, &m);
if(n > m) swap(n, m); ///n < m
dfs(n, m);
ll siz = v.size();
printf("%lld\n", siz);
for(ll i = 0; i < siz; i++){
printf("%d%c", v[i], i == siz - 1 ? '\n' : ' ');
}
}
return 0;
}