題意:定義一種無進位加法運算,給你n個正整數,問你取出兩個數,使得他們加起來和最大/最小是多少。spa
無進位加法運算,實際上是一種位運算,跟最大xor那個套路相似,很容易寫出對於每一個數字,其對應的最優數字是誰,就對於十叉的字典樹,貪心地儘可能往使結果更優越的方向走便可。blog
#include<cstdio> #include<algorithm> using namespace std; int ch[1000010*20][10],sz; typedef long long ll; ll pw[20]; void Insert(ll x) { int U=0; for(int i=18;i>=0;--i){ if(!ch[U][x/pw[i]%10ll]){ ch[U][x/pw[i]%10ll]=++sz; } U=ch[U][x/pw[i]%10ll]; } } ll qmax(ll x){ int U=0; ll res=0; for(int i=18;i>=0;--i){ int wei=x/pw[i]%10ll; int k=9; for(int j=9-wei;j>=0;--j,--k){ if(ch[U][j]){ res+=(ll)k*pw[i]; wei=j; goto OUT; } } for(int j=9;j>9-wei;--j,--k){ if(ch[U][j]){ res+=(ll)k*pw[i]; wei=j; goto OUT; } } OUT: U=ch[U][wei]; } return res; } ll qmin(ll x){ int U=0; ll res=0; for(int i=18;i>=0;--i){ int wei=x/pw[i]%10ll; int k=0; for(int j=9-wei+1;j<=9;++j,++k){ if(ch[U][j]){ res+=(ll)k*pw[i]; wei=j; goto OUT2; } } for(int j=0;j<=9-wei;++j,++k){ if(ch[U][j]){ res+=(ll)k*pw[i]; wei=j; goto OUT2; } } OUT2: U=ch[U][wei]; } return res; } int n; ll a[1000005]; int main(){ //freopen("a.in","r",stdin); ll ans1=0,ans2=9000000000000000000ll; pw[0]=1; for(int i=1;i<=18;++i){ pw[i]=pw[i-1]*10ll; } scanf("%d",&n); for(int i=1;i<=n;++i){ scanf("%I64d",&a[i]); if(i>1){ ans1=max(ans1,qmax(a[i])); ans2=min(ans2,qmin(a[i])); } Insert(a[i]); } printf("%I64d %I64d\n",ans2,ans1); return 0; }