Wannafly模拟赛5 待更新 题解

来源:互联网 发布:伪娘丁丁套淘宝 编辑:程序博客网 时间:2024/05/20 18:45

题目链接:https://www.nowcoder.com/acm/contest/18#question


A:考虑到均分一定比不均分好,我们就容易反推回去了。

#include <bits/stdc++.h>using namespace std;int work(int n, int cnt){    vector <int> q(cnt, n/cnt);    for(int i=0; i<n%cnt; i++) q[i]++;    int s = 0;    for(int i=0,p=0,sz=q.size(); i<sz; i++) s+=p*q[i], p+=q[i];    return s;}int main(){    int n, m;    scanf("%d %d", &n,&m);    int i;    for(i=2; i<=n; i++) if(work(n,i)>=m) break;    return 0*printf("%d\n", i==n+1?-1:i-1);    return 0;}

D:直接二进制枚举哪些是加完要重排的,然后DFS即可。复杂度10!*32

#include <bits/stdc++.h>using namespace std;typedef long long LL;LL n, x, ans, a[10];LL sum;void dfs(int dep, LL now, bool vis[]){    if(dep==n){        sum = max(sum, now);        return;    }    if(vis[dep]){        LL x = now+a[dep];        vector <int> v;        LL tmp = x;        while(x){            v.push_back(x%10);            x/=10;        }        sort(v.begin(),v.end());        do{            LL t = 0;            for(LL i=0; i<v.size(); i++){                 t = t*10 + v[i];            }            dfs(dep+1, t, vis);        }while(next_permutation(v.begin(),v.end()));    }    else dfs(dep+1, now+a[dep], vis);}int main(){    scanf("%lld", &n);    ans = 0;    for(LL i=0; i<n; i++) scanf("%lld", &a[i]);    LL mask = (1<<n);    for(LL i=0; i<mask; i++){        bool vis[10]={0};        for(LL j=0; j<n; j++){            if(i&(1<<j)) vis[j]=1;        }        sum = 0;        dfs(0, 0, vis);        ans = max(ans, sum);    }    printf("%lld\n", ans);    return 0;}

E:我们假如每次都刷一个木板,即一竖行,那么需要n次刷完,可见这是一个ans的最大值。就是最差的情况下我这样刷最多为n刷。如果我们选择一横行的刷,而n个木板中最短的为mi,那么我们可以花min刷,把他们都刷成a [ i ] - mi的高度,那么剩下来的栅栏又变成了开始的情况,我们可以在选择前面不为0的x个,继续按上面的方法刷,可见是一个递归调用即可。要特别注意的是前面的条件,就是刷x个木板,最多用x刷,如果某一次求得大于x,那么取x。


#include <bits/stdc++.h>using namespace std;const int maxn = 5010;int n, a[maxn], tmp;void gao(int l, int r){    int mx = -1, mi = INT_MAX;    for(int i=l; i<r; i++){        mx = max(mx, a[i]);        mi = min(mi, a[i]);    }    if(mx == mi){        tmp += min(mx, r-l);        return;    }    for(int i=l; i<r; i++) a[i] -= mi;    mi = min(mi, r-l);    tmp += mi;    for(int i=l; i<r; i++){        if(a[i]>0){            for(int j=i; j<r; j++){                if(a[j]==0||(j==(r-1)&&a[j]>0)){                    if(j==(r-1)&&a[j]>0) j++;                    int temp2 = tmp;                    gao(i, j);                    if(tmp-temp2>(j-i)){//判断如果求得的值比直接一行一行刷更大的话,取更小的                        tmp = temp2+(j-i);                    }                    i=j;                    break;                }            }        }    }}int main(){    scanf("%d", &n);    for(int i=0; i<n; i++) scanf("%d", &a[i]);    tmp = 0;    gao(0, n);    return 0*printf("%d\n", min(tmp, n));}


原创粉丝点击