题目链接: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));
}