题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5231
题意:
求一个数n 最少,可以由几个这样 1...x的数的和组成
分析:
多写几组可以发现规律 最多由三组组成,然后枚举一个值,然后用夹逼求另外两个的值。
代码如下:
#include <iostream> #include <cstdio> #include <map> #include <vector> #include <cstring> #include <algorithm> #define PB push_back #define MP make_pair #define REP(i,n) for(int i=0;i<(n);++i) #define FOR(i,l,h) for(int i=(l);i<=(h);++i) #define DWN(i,h,l) for(int i=(h);i>=(l);--i) #define IFOR(i,h,l,v) for(int i=(h);i<=(l);i+=(v)) #define CLR(vis) memset(vis,0,sizeof(vis)) #define MST(vis,pos) memset(vis,pos,sizeof(vis)) #define MAX3(a,b,c) max(a,max(b,c)) #define MAX4(a,b,c,d) max(max(a,b),max(c,d)) #define MIN3(a,b,c) min(a,min(b,c)) #define MIN4(a,b,c,d) min(min(a,b),min(c,d)) #define PI acos(-1.0) #define INF 1000000000 #define LINF 1000000000000000000LL #define eps 1e-8 #define LL long long #define maxn 120010 using namespace std; int a[maxn]; map<int ,int >mp; vector<int >ans; int cnt; void init(){ CLR(a); mp.clear(); LL sum=0; cnt=0; FOR(i,1,maxn-1){ a[i]=a[i-1]+i; mp[a[i]]=i; cnt++; if(a[i]>123456789) return; } } int main() { init(); int t,n; scanf("%d",&t); while(t--){ scanf("%d",&n); int pos=lower_bound(a+1,a+cnt+1,n)-a; if(a[pos]==n){ printf("%d\n",pos); continue; } vector<int >ans; REP(i,pos+1){ ans.clear(); if(i) ans.push_back(i); bool tag = 0; int l = 1,r=pos; while(l<=r){ if(a[l]+a[r]<n-a[i]) l++; else if(a[l]+a[r]>n-a[i]) r--; else{ ans.push_back(l); ans.push_back(r); tag = 1; break; } } if(tag){ printf("%d",ans[0]); FOR(j,1,ans.size()-1) printf(" %d",ans[j]); puts(""); break; } } } return 0; }
方法二:
迭代DFS,我们枚举深度,然后做DFS就可以得到最少的了。
代码如下:
#include <iostream> #include <cstdio> #include <map> #include <vector> #include <cstring> #include <algorithm> #define PB push_back #define MP make_pair #define REP(i,n) for(int i=0;i<(n);++i) #define FOR(i,l,h) for(int i=(l);i<=(h);++i) #define DWN(i,h,l) for(int i=(h);i>=(l);--i) #define IFOR(i,h,l,v) for(int i=(h);i<=(l);i+=(v)) #define CLR(vis) memset(vis,0,sizeof(vis)) #define MST(vis,pos) memset(vis,pos,sizeof(vis)) #define MAX3(a,b,c) max(a,max(b,c)) #define MAX4(a,b,c,d) max(max(a,b),max(c,d)) #define MIN3(a,b,c) min(a,min(b,c)) #define MIN4(a,b,c,d) min(min(a,b),min(c,d)) #define PI acos(-1.0) #define INF 1000000000 #define LINF 1000000000000000000LL #define eps 1e-8 #define LL long long #define maxn 120010 using namespace std; int a[maxn]; map<int ,int >mp; vector<int >ans; int cnt; void init(){ CLR(a); mp.clear(); LL sum=0; cnt=0; FOR(i,1,maxn-1){ a[i]=a[i-1]+i; mp[a[i]]=i; cnt++; if(a[i]>123456789) return; } } bool flag; void dfs(int dep,int val){ if(dep==1){ if(mp[val]){ ans.push_back(mp[val]); flag = true; } return; } int pos = upper_bound(a+1,a+cnt+1,val)-a; DWN(i,pos-1,1){ ans.push_back(mp[a[i]]); dfs(dep-1,val-a[i]); if(flag) return; ans.erase(--ans.end()); } } int main() { init(); int t,n; scanf("%d",&t); while(t--){ scanf("%d",&n); flag=false; ans.clear(); FOR(i,1,cnt){ dfs(i,n); if(flag){ printf("%d",ans[0]); FOR(i,1,ans.size()-1) printf(" %d",ans[i]); puts(""); break; } } } return 0; }