Beautiful Now
Time Limit: 5000/2500 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 4513 Accepted Submission(s): 457
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.
Let the decimal representation of n as (x1x2⋯xm)10 satisfying that 1≤x1≤9, 0≤xi≤9 (2≤i≤m), which means n=∑mi=1xi10m−i. In each swap, Anton can select two digits xi and xj (1≤i≤j≤m) and then swap them if the integer after this swap has no leading zero.
Could you please tell him the minimum integer and the maximum integer he can obtain after k swaps?
Input
The first line contains one integer T, indicating the number of test cases.
Each of the following T lines describes a test case and contains two space-separated integers n and k.
1≤T≤100, 1≤n,k≤109.
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
Statistic | Submit | Clarifications | Back
题意:给定数N(1<=N<=1e9),k(1<=k<=1e9),求对N的任意两位数交换至多k次能得到的最小与最大的数,每一次交换之后不能出现前导零。
题解 保存下标,全排列枚举下标 这里用到了一个非常神奇的c++内置函数next_permutation()函数
多校的时候我看到这个题我就觉得可以用dfs暴搜一下,然而学艺不精,没搞出来,后来看了看大佬的思路发现了这么一个c++的全排列函数 然后就很简单了
这是一个c++函数,包含在头文件<algorithm>里面,下面是基本格式
1 int a[];
2 do{
3
4 }while(next_permutation(a,a+n));
下面的代码可产生1~n的全排列。
#include <stdio.h>
#include <algorithm>
using namespace std;
int main(){
int n;
while(scanf("%d",&n)&&n){
int a[1000];
for(int i=0;i<n;i++){
scanf("%d",&a[i]);
}
sort(a,a+n);//可以自行测试一下删除后的结果
do{
for(int i=0;i<n;i++)
printf("%d ",a[i]);
printf("\n");
}while(next_permutation(a,a+n));
}
return 0;
}
例如输入
3
1 0 2
如果有sort()
输出为
0 1 2
0 2 1
1 0 2
1 2 0
2 0 1
2 1 0
若无
则输出为
1 0 2
1 2 0
2 0 1
2 1 0
可以发现少了许多种组合方法。
不过,仔细比较各种组合方法和有无sort()的输出,可以发现函数next_permutation()是按照字典序产生排列的,并且是从数组中当前的字典序开始依次增大直至到最大字典序。
所以全排列会从你所给序列的字典序输出比其大的全排列序列,比其小的抹掉了,因此再用这个内置函数的时候注意sort
本题因为是从0开始到cnt的字典序最小,所以可以不用sort
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <cmath>
#include <math.h>
#include <cstring>
#include <string>
#include <queue>
#include <deque>
#include <stack>
#include <stdlib.h>
#include <list>
#include <map>
#include <utility>
#include <time.h>
#include <set>
#include <bitset>
#include <vector>
#define pi acos(-1.0)
#define inf 0x3f3f3f3f
#define linf 0x3f3f3f3f3f3f3f3f
#define ms(a,b) memset(a,b,sizeof(a))
#define INF 0x3f3f3f3f
#define ll long long
const int maxn=1e5+5;
using namespace std;
int read()
{int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*f;}
ll qpow(ll x, ll y, ll mod){ll s=1;while(y){if(y&1)s=s*x%mod;x=x*x%mod;y>>=1;}return s;}
ll a[10],vis[10],pos[10];
ll n,k;
ll cnt;
ll judge()
{
ms(vis,0);
ll temp=0;
for(int i=0;i<cnt;i++)//暴力一边pos[i]里的数
{
if(vis[i])continue;
ll cnt1=0;
while(!vis[i])
{
cnt1++;
vis[i]=1;
i=pos[i]; //pos[i]排列后的位置 i排列前的位置
}
cnt1--;//两两交换最后肯定会多交换一下
temp+=cnt1;
if(temp>k)return 0;
}
return 1;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
ll minn=INF;
ll maxn=0;
scanf("%lld%lld",&n,&k);
ll temp=n;
cnt=0;
while(temp)
{
a[cnt++]=temp%10;
temp/=10;
}
reverse(a,a+cnt);
for(int i=0;i<cnt;i++)
pos[i]=i;
//sort(pos,pos+cnt);
do
{
if(a[pos[0]]!=0 && judge())//没有前导零,并且交换的次数在k次之内
{
ll ans=0;
for(int i=0;i<cnt;i++)ans=ans*10+a[pos[i]];
if(ans>maxn)maxn=ans;
if(ans<minn)minn=ans;
}
}while(next_permutation(pos,pos+cnt));
printf("%lld %lld\n",minn,maxn);
}
return 0;
}