78分,T,求调,有注释
查看原帖
78分,T,求调,有注释
428053
巫晴枫123456楼主2023/11/14 19:25
#include<bits/stdc++.h>
using namespace std;
int n,m,k,ans,p,x[10000001],nex[10000001];
bool vis[10000001];
int ef(int l,int r,int re){//二分查找
	while(l<r){
	        int mid=(l+r)>>1;
	        if(x[mid]<=re) r=mid;
	        else l=mid+1;
	}
	return l;
}
void dfs(int id,int le,int re){
	if(p)	return ;//回溯
	int i =  ef(le+1,n,re);
	if(re==0){
		if(id == k){//回溯
			p = 1;
			return ;
		}
		i=1;
		while(vis[i]&&i<n)	i++;//未用中最大的 
		vis[i] = 1;
		dfs(id+1,i,ans-x[i]);
		vis[i] = 0;//撤销标记
		if(p)	return ;//回溯 
	}
	for(i; i <= n; i++){
		if(!vis[i]&&re>=x[i]){//可刑 
			vis[i] = 1;
			if(p)	return ;//回溯
			dfs(id,i,re-x[i]);
			vis[i] = 0;
			i = nex[i];//nex数组寻找下一个
			if(i==n)	return ;//如果==则跳
		}
	}
	return ;
}
bool cmp(int a,int b){
	return a > b;//大至小找优
}
int main(){
	cin >> n;
	for(int i = 1; i <= n; i++){
		cin >> x[i];
		m += x[i];
	}
	sort(x+1,x+n+1,cmp);
	nex[n] = n;
	for(int i=n-1; i > 0; i--){//预处理 
        if(x[i] == x[i+1]) nex[i]=nex[i+1];
        else nex[i]=i;
    }
	ans = x[1];//从最小值开始
	while(ans <= m/2){
		if(m%ans==0){//整除则可算 
			k = m/ans;
			vis[1] = 1;
			dfs(1,1,ans-x[1]);
			if(p){
				cout << ans;
				return 0;
			}
		}
		ans++;
	}
	cout << m;
	return 0;
}
2023/11/14 19:25
加载中...