题意:给定数N(1<=N<=1e9),k(1<=k<=1e9),求对N的任意两位数交换至多k次能得到的最小与最大的数,每一次交换之后不能出现前导零。

因为N最多只有10位,且给了2500ms,当时觉得可以枚举全排列,再判断前导零和最少交换次数。

最少交换次数是(每个循环节中的个数-1)之和。

当时想的是全排列N的每位数,但是这样会出现一个问题:N中可能出现相同的数,这样求循环节中元素个数就会很困难。‘

其实应该对下标进行全排列,因为下标是不可能相同的,这样就可以O(len) 地计算出每个排列的最少交换次数。然后取符合条件的最小最大的数为答案。

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn =;
const LL INF= (1LL)<<;
int k,len;
int pos[maxn];
int num[maxn];
bool vis[maxn]; int check(){
memset(vis,,sizeof(vis));
int cnt =;
for(int i=;i<len;++i){
if(vis[i]) continue;
int tmp=;
while(!vis[i]){
tmp++;
vis[i]=;
i = pos[i];
}
cnt += tmp-;
if(cnt>k) return ;
}
return cnt;
} char str[maxn];
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
int T;
scanf("%d",&T);
while(T--){
memset(str,,sizeof(str));
scanf("%s %d",str,&k);
len = strlen(str);
LL N=;
for(int i=;i<len;++i) num[i] = str[i]-'',pos[i]=i,N = N*+num[i];
LL ans1= N,ans2=N;
do{
if(num[pos[]]!= && check()){
LL tmp =;
for(int i=;i<len;++i){
tmp*=;
tmp+= num[pos[i]];
}
if(tmp<ans1) ans1=tmp;
if(tmp>ans2) ans2=tmp;
}
}while(next_permutation(pos,pos+len));
printf("%lld %lld\n",ans1,ans2);
}
return ;
}

最新文章

  1. sql基础大全
  2. Writing Clean Code 读后感
  3. Linux常用命令组合
  4. 你不知道的this—JS异步编程中的this
  5. oracle连接数据
  6. android studio 预览保持,因为是SDK版本过高,可以点击小图标机器人修改SDK版本号。
  7. python数据类型和3个重要函数
  8. jquery表格提交验证
  9. python 导入informixdb模块
  10. 开发函数计算的正确姿势 —— 使用 Fun Local 本地运行与调试
  11. 学号:20165239 预备作业3 Linux安装及学习
  12. js中字符替换函数String.replace()使用技巧
  13. np.mat()和np.transpose
  14. 在k8s中搭建可解析hostname的DNS服务
  15. SCTF 2014 PWN400 分析
  16. python opencv3 cornerHarris 角点检测
  17. VMware安装Ubuntu
  18. CountDownLatch 使用(模拟一场比赛)
  19. mysql数据库建表
  20. Gym101128F:Landscaping

热门文章

  1. 数据库I/O:CMP、Hibernate
  2. 小白用advanced installer建安装包
  3. Anaconda2+Theano 安装过程中的所有的坑。。。
  4. java基础-集合笔记
  5. 1、手把手教React Native实战之环境搭建
  6. 面试题思考:Cookie 和 Session的区别
  7. XAMPP修改mysql的默认密码的三种方法
  8. iOS设置导航栏透明度
  9. Java算法之“兔子问题”
  10. 一篇搞定vue-router