题目描述
乔治有一些同样长的小木棍,他把这些木棍随意砍成几段,直到每段的长都不超过5050。
现在,他想把小木棍拼接成原来的样子,但是却忘记了自己开始时有多少根木棍和它们的长度。
给出每段小木棍的长度,编程帮他找出原始木棍的最小可能长度。
输入输出格式
输入格式:
共二行。
第一行为一个单独的整数N表示砍过以后的小木棍的总数,其中N≤65N≤65
(管理员注:要把超过5050的长度自觉过滤掉,坑了很多人了!)
第二行为NN个用空个隔开的正整数,表示NN根小木棍的长度。
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 #include<cmath> 6 #include<vector> 7 #include<queue> 8 #include<map> 9 #include<set> 10 #include<stack> 11 using namespace std; 12 const int maxn=100007; 13 const int INF=0x7f7f7f7f; 14 int n,m,sum,stp,ans=INF,req; 15 int len[maxn],s[maxn],nxt[maxn]; 16 bool is[maxn],usd[maxn],bj; 17 void gettable(){ 18 for(int i=2;i<=sqrt(sum);i++){ 19 if(sum%i==0){ 20 if(i>=len[1]) s[++stp]=i; 21 if(i!=(sum/i)) if(sum/i>=len[1]) s[++stp]=sum/i; 22 } 23 } 24 } 25 bool cmp(int a,int b){ 26 return a>b; 27 } 28 /*bool dfs(int now,int st,int lft){ 29 bool flg=false; 30 if(lft==0&&st==sum/req) return true; 31 if(lft==0){ 32 int i; 33 for(i=1;i<=n;i++){ 34 if(!usd[i]){usd[i]=true;flg=true;break;} 35 } 36 if(flg) dfs(i,st+1,req-len[i]); 37 } 38 bool flag=false; 39 for(int i=now+1;i<=n;i++){ 40 if(usd[i]) continue; 41 if(lft>=len[i]){ 42 usd[i]=true;flag=true; 43 if(dfs(i,st,lft-len[i])) return true; 44 else return false; 45 usd[i]=false; 46 } 47 } 48 if(!flag) return false; 49 }*/ 50 void dfs(int k,int last,int rest){ 51 int i,j; 52 if(rest==0){ 53 if(k==(sum/req)){bj=1;return;} 54 for(i=1;i<=n;i++) 55 if(!usd[i]){usd[i]=true;break;} 56 dfs(k+1,i,req-len[i]); 57 usd[i]=false; 58 if(bj) return; 59 } 60 int l=last+1, r=n, mid; 61 while(l<=r){ 62 mid=(l+r)/2; 63 if(len[mid]<=rest) r=mid-1; 64 else l=mid+1; 65 } 66 for(i=l;i<=n;i++){ 67 if(!usd[i]){ 68 usd[i]=1; 69 dfs(k,i,rest-len[i]); 70 usd[i]=0; 71 if(bj) return; 72 if(rest==len[i]) return; 73 i=nxt[i]; 74 if(i==n) return; 75 } 76 } 77 } 78 int main(){ 79 cin>>m; 80 for(int i=1;i<=m;i++){ 81 int a;cin>>a;if(a>50) continue; 82 len[++n]=a;sum+=len[n]; 83 } 84 sort(len+1,len+n+1,cmp); 85 gettable(); 86 sort(s+1,s+n+1,cmp); 87 nxt[n]=n; 88 for(int i=n-1;i>=1;i--){ 89 if(len[i]==len[i+1]) nxt[i]=nxt[i+1]; 90 else nxt[i]=i; 91 } 92 for(int i=1;i<=stp;i++){ 93 if(is[i]) continue; 94 memset(usd,false,sizeof(usd)); 95 bj=false;usd[1]=true;req=s[i]; 96 dfs(1,1,req-len[1]); 97 if(!bj){ 98 for(int j=i+1;j<=stp;j++){ 99 if(s[i]%s[j]==0) is[j]=true; 100 } 101 } 102 else ans=min(ans,s[i]); 103 } 104 if(ans==INF) cout<<sum<<endl; 105 else cout<<ans<<endl; 106 }