思路:一开始想暴力,结果看到数据1e18,肯定要超时。然后想了一下。一开始可以把a的每一个数字对应的个数用数组存起来,如果b的位数大于a的位数,我们找的答案只要把数字从大到小放在位数从高到低的位置。
如果b的位数等于a的,我们就从高位到低位逐一枚举,每个位都填小与等于b的该位的数字。这里要注意如果有一位枚举的数小与b对应的位的数字,剩下的每个位就直接找最大的数字填入就好了。如果有一位没有找到小于等于该位的数字,就退一位,把那一位的数字减小,一直没找到就一直退位重新匹配。这也是代码里出现那个while循环的原因。
(当初一直在某一位为0这个问题上纠结。其实因为题中提到了,答案一定存在,那么如果某一位为0,我们要么肯定能匹配为0,要么前面的高位已经小与对应的位了,0对应的位我们只要匹配上最大的数就好了。)
每次都啰嗦半天···上代码——
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
char s1[20],s2[20];
typedef long long ll;
ll x,y;
bool flag;
int a[11],b[20],ans[20];
int Find(int t)
{
int i;
if(flag==false)
for(i=t;i>=0;i--)
{
if(i<=t&&a[i]!=0)
return i;
}
if(flag==true)
{
for(i=9;i>=0;i--)
{
if(a[i]!=0)
return i;
}
}
return -1;
}
void solve()
{
int i,j,t,n1,n2;
flag=false;
memset(a,0,sizeof(a));
n1=strlen(s1);
n2=strlen(s2);
for(i=0;s1[i];i++)
a[s1[i]-'0']++;
for(i=0;s2[i];i++)
b[i]=s2[i]-'0';
if(n2==n1)
{
for(i=0;i<n2;i++)
{
t=Find(b[i]);
if(t!=-1)
{
ans[i]=t;
if(t!=b[i])
flag=true;
a[t]--;
}
if(t==-1)
{
while(t==-1)
{
i--;
a[ans[i]]++;
t=Find(b[i]-1);
}
ans[i]=t;
a[t]--;
flag=true;
}
}
}
if(n2>n1)
{
for(i=0;i<n1;i++)
{
t=Find(9);
ans[i]=t;
a[t]--;
}
}
for(i=0;i<n1;i++)
cout<<ans[i];
cout<<endl;
}
int main()
{
while(cin>>s1>>s2)
{
solve();
}
return 0;
}