2020牛客多校第七场 Mask Allocation

题意
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 < m 1 m m m . . . m n 考虑n!=m情况,方便起见,直接令n<m\\思考:\\(1)m、m、m、...、m,共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个
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)很相似,产生联想,这会不会是动态规划,\\由一个状态转移另外一个状态呢?

证明
d p ( n , m ) n m ( n < m ) 设dp(n, m)表示分解n*m的方案(注意n<m)
d p ( n , , m ) d p ( 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
d p ( n , m ) = d p ( 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
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显然是最优秀的转移
d p ( ) d p ( c , c ) c c dp()初始状态很简单,即dp(c,c)为c个c

#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;
}

猜你喜欢

转载自blog.csdn.net/weixin_44412226/article/details/107735816