2020牛客多校第七场 Mask Allocation

题意
分 解 n ∗ m , 使 得 满 足 两 个 条 件 : ( 1 ) 分 解 的 数 中 可 以 组 合 成 n 组 , 每 组 的 值 为 m ( 2 ) 分 解 的 数 中 可 以 组 合 成 m 组 , 每 组 的 值 为 n 分解n*m,使得满足两个条件:\\(1)分解的数中可以组合成n组,每组的值为m\\(2)分解的数中可以组合成m组,每组的值为n nm使1nm2mn
要 使 得 分 解 的 个 数 少 , 若 相 同 输 出 字 典 序 最 大 的 一 种 方 案 要使得分解的个数少,若相同输出字典序最大的一种方案 使
思路
考 虑 n = = m 情 况 简 单 直 接 输 出 n 个 n 即 可 , 显 然 考虑n==m情况\\简单直接输出n个n即可,显然 n==mnn
考 虑 n ! = m 情 况 , 方 便 起 见 , 直 接 令 n < m 思 考 : ( 1 ) m 、 m 、 m 、 . . . 、 m , 共 n 个 考虑n!=m情况,方便起见,直接令n<m\\思考:\\(1)m、m、m、...、m,共n个 n!=m便n<m1mmm...mn
( 2 ) n 、 n 、 n 、 . . . . 、 n , 共 n 个 (2)n、n、n、....、n,共n个 2nnn....nn
把 ( 1 ) 中 的 每 个 m 都 减 掉 n 可 得 到 m − n 共 n 个 把(1)中的每个m都减掉n可得到m-n共n个 1mnmnn
( 3 ) m − n 、 m − n 、 m − n 、 . . . 、 m − n , 共 n 个 (3)m-n、m-n、m-n、...、m-n,共n个 3mnmnmn...mn,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<m) dp(n,m)nm(n<m)
d p ( n , , m ) 与 d p ( m − n , n ) 关 系 呢 ? dp(n,,m)与dp(m - n, n)关系呢? dp(n,,m)dp(mn,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):nmmndp(mn,n):mnnnmn
d p ( n , m ) = d p ( m − n , n ) + n 个 n dp(n, m) = dp(m -n, n)+n个n dp(n,m)=dp(mn,n)+nn

很显然
m − n 组 n + n 组 n = m 组 n m-n组n+n组n=m组n mnn+nn=mn
n 组 m − n + n 组 n = n 组 m n组m-n+n组n=n组m nmn+nn=nm

因 为 d p ( m − n , n ) 是 最 优 状 态 , + n 个 n 显 然 是 最 优 秀 的 转 移 因为dp(m-n,n)是最优状态,+n个n显然是最优秀的转移 dp(mn,n)+nn
d p ( ) 初 始 状 态 很 简 单 , 即 d p ( c , c ) 为 c 个 c dp()初始状态很简单,即dp(c,c)为c个c dp()dp(c,c)cc

#include <bits/stdc++.h>
 
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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值