Beautiful NowTime Limit: 5000/2500 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)Total Submission(s): 1060 Accepted Submission(s): 366 Problem Description Anton has a positive integer n , however, it quite looks like a mess, so he wants to make it beautiful after k swaps of digits.
Input The first line contains one integer T , indicating the number of test cases.
Output For each test case, print in one line the minimum integer and the maximum integer which are separated by one space.
Sample Input 5 12 1 213 2 998244353 1 998244353 2 998244353 3
Sample Output 12 21 123 321 298944353 998544323 238944359 998544332 233944859 998544332
Source 2018 Multi-University Training Contest 5
Recommend chendu | We have carefully selected several similar problems for you: 6361 6360 6359 6358 6357 |
题意:给一个数字n,可以各个位之间交换,再进行最多k次交换后,能构成的最小和最大的数是多少。
分析:拿贪心搞的话策略总是不完备,数据量给的刚好,所以就爆搜吧,需要一些剪枝,不然也是TLE。
1、首先对于k大于等数字n的长度-1就一定可以把所有位都换一遍,那么最大结果一定是这些数字排列后所构成的最大结果,最小结果也是这些数字排列后形成的最小结果。
2、对于k比较小的情况直接dfs,以找最小数字为例,每次都去找剩余位上最小的数字是多少,找到了就用当前位和它交换位置,进入下一个状态。
3、具体过程看注释吧。
#include<stdio.h>
#include<algorithm>
#include<iostream>
#include<string.h>
#include<vector>
#include<stdlib.h>
#include<math.h>
#include<queue>
#include<deque>
#include<ctype.h>
#include<map>
#include<set>
#include<stack>
#include<string>
#define INF 100
#define FAST_IO ios::sync_with_stdio(false)
const double PI = acos(-1.0);
const double eps = 1e-6;
const int MAX=1e5+10;
const int mod=1e9+7;
typedef long long ll;
using namespace std;
#define gcd(a,b) __gcd(a,b)
inline ll lcm(ll a,ll b){return a/gcd(a,b)*b;}
inline ll qpow(ll a,ll b){ll r=1,t=a; while(b){if(b&1)r=(r*t)%mod;b>>=1;t=(t*t)%mod;}return r;}
inline ll inv1(ll b){return qpow(b,mod-2);}
inline ll exgcd(ll a,ll b,ll &x,ll &y){if(!b){x=1;y=0;return a;}ll r=exgcd(b,a%b,y,x);y-=(a/b)*x;return r;}
inline ll read(){ll x=0,f=1;char c=getchar();for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;for(;isdigit(c);c=getchar()) x=x*10+c-'0';return x*f;}
//freopen( "in.txt" , "r" , stdin );
//freopen( "data.txt" , "w" , stdout );
ll n,k;
string s;
string mins,maxs;
string tmins,tmaxs;
int cmp(char x,char y)
{
return x>y;
}
void dfs1(ll indx,ll cut,string x)//最小的情况
{
if(indx==s.length()-1 || cut>k-1)
{
tmins=min(tmins,x);
return ;
}
if(x[indx]==mins[indx])//当前数字已经在最优位置上,不用再交换了。
{
dfs1(indx+1,cut,x);
return;
}
char p=INF;
for(ll i=indx+1;i<x.length();i++)
{
if(indx==0 && x[i]=='0')
continue;
p=min(p,x[i]);
}
if(p==INF)
{
dfs1(indx+1,cut,x);
return ;
}
for(ll i=indx+1;i<x.length();i++)
{
if(x[i]==p)
{
swap(x[indx],x[i]);
dfs1(indx+1,cut+1,x);
swap(x[indx],x[i]);
}
}
}
void dfs2(ll indx,ll cut,string x)//最大的情况
{
if(indx==s.length()-1 || cut>k-1)
{
tmaxs=max(tmaxs,x);
return ;
}
if(x[indx]==maxs[indx])//
{
dfs2(indx+1,cut,x);
return ;
}
char p=-1;
for(ll i=indx+1;i<x.length();i++)
p=max(p,x[i]);
for(ll i=indx+1;i<x.length();i++)
{
if(x[i]==p)
{
swap(x[indx],x[i]);
dfs2(indx+1,cut+1,x);
swap(x[indx],x[i]);
}
}
}
void solve()
{
tmins=tmaxs=s;
dfs1(0,0,s);
dfs2(0,0,s);
}
void init()
{
cin>>n>>k;
s.clear();
while(n)
{
s=s+(char)(n%10+'0');
n=n/10;
}
reverse(s.begin(),s.end());//反转。
mins=s;
maxs=s;
sort(mins.begin(),mins.end());
sort(maxs.begin(),maxs.end(),cmp);
if(mins[0]=='0')//最小情况时开头为0用次小的换掉这个0。
{
int indx=0;
while(mins[indx]=='0')
indx++;
swap(mins[0],mins[indx]);
}
}
int main()
{
ll T;
cin>>T;
while(T--)
{
init();
if(k>=s.length()-1)//特判 k大于n的长度一定可以构成最小和最大的这种情况。
cout<<mins<<' '<<maxs<<endl;
else
{
solve();
cout<<tmins<<' ';
cout<<tmaxs<<endl;
}
}
return 0;
}