2020牛客暑期多校第七场 B - Mask Allocation(思维)

传送门


首先假设 n < m n<m n<m,然后不难知道分的每堆口罩的最大数量不能超过 n n n

观察样例发现最优的分法似乎需要先分出 n n n n n n,再仔细思考一下,如果是 4    8 4~~8 4  8这组数据,显然需要分为 8 8 8 4 4 4,这样也满足了 4 4 4 8 8 8

然后得出我们在分出 ( m / n ) ∗ n (m/n)*n (m/n)n n n n之后,然后考虑满足有 n n n m m m个口罩,那么下面需要分的是 n n n m % n m\%n m%n口罩,现在已经不难看出,这是一个递归的程序,递归的边界是 n = = 1 n==1 n==1时直接分每堆 1 1 1个口罩

为什么不需要考虑这样写能否分为 m m m n n n个口罩,首先已经有了 n n n n n n个口罩,第一次递归的是 d f s ( m % n , n ) dfs(m\%n,n) dfs(m%n,n),也就是下次分的是按照满足最大为 n n n的情况去分,这样剩下的堆凑出的一定能满足 m − n m-n mn n n n

这个推理过程和 g c d gcd gcd有异曲同工之妙

#include <bits/stdc++.h>
#include <unordered_map>
#include <unordered_set>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define ins insert
#define Vector Point
#define lowbit(x) (x&(-x))
#define mkp(x,y) make_pair(x,y)
#define mem(a,x) memset(a,x,sizeof a);
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef pair<double,double> pdd;
const double eps=1e-8;
const double pi=acos(-1.0);
const int inf=0x3f3f3f3f;
const double dinf=1e300;
const ll INF=1e18;
const int Mod=1e9+7;
const int maxn=2e5+10;

vector<int> ans;

void dfs(int n,int m){
    if(n==0) return;
    if(n==1){
        for(int i=0;i<m;i++) ans.push_back(1);
        return;
    }
    for(int i=0;i<(m/n)*n;i++) ans.push_back(n);
    dfs(m%n,n);
}

int main(){
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    ios_base::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    int t,n,m;
    cin>>t;
    while(t--){
        cin>>n>>m;
        ans.clear();
        if(n>m) swap(n,m);
        dfs(n,m);
        sort(ans.begin(),ans.end(),greater<int>());
        cout<<ans.size()<<"\n";
        for(auto i: ans) cout<<i<<" ";
        cout<<"\n";
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值