HDU 6351 (Beautiful Now) 2018 Multi-University Training Contest 5
2024-09-04 11:10:55
题意:给定数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 ;
}
最新文章
- sql基础大全
- Writing Clean Code 读后感
- Linux常用命令组合
- 你不知道的this—JS异步编程中的this
- oracle连接数据
- android studio 预览保持,因为是SDK版本过高,可以点击小图标机器人修改SDK版本号。
- python数据类型和3个重要函数
- jquery表格提交验证
- python 导入informixdb模块
- 开发函数计算的正确姿势 —— 使用 Fun Local 本地运行与调试
- 学号:20165239 预备作业3 Linux安装及学习
- js中字符替换函数String.replace()使用技巧
- np.mat()和np.transpose
- 在k8s中搭建可解析hostname的DNS服务
- SCTF 2014 PWN400 分析
- python opencv3 cornerHarris 角点检测
- VMware安装Ubuntu
- CountDownLatch 使用(模拟一场比赛)
- mysql数据库建表
- Gym101128F:Landscaping