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

传送门


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

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

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

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

这个推理过程和 g c d 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;
}

猜你喜欢

转载自blog.csdn.net/qq_44691917/article/details/107890327