原题链接:CF1560D
题意
对于一个整数n,可以以任意顺序进行以下两种操作中的一种。
- 删除n中的任意一位(会留下具有前导0的数字)
- 在n的末尾加上任意一个数字
求出使n转化为2k所需要的最少操作次数
思路
由于这题是对数位进行操作,可以考虑直接暴力求解。
对于n转化为2k的过程可以理解为两个步骤
- 在n中删除x个数字
- 在n末尾加上y个数字
只需求出n与2k的子序列长度即可求出x与y的值
代码如下:
代码
#include <bits/stdc++.h>
using namespace std;
//此处先预处理出了2的64次方的值
string ex[] = {"1","2","4","8","16","32","64","128",
"256","512","1024","2048","4096","8192","16384","32768",
"65536","131072","262144","524288","1048576","2097152",
"4194304","8388608","16777216","33554432","67108864",
"134217728","268435456","536870912","1073741824","2147483648",
"4294967296","8589934592","17179869184","34359738368",
"68719476736","137438953472","274877906944","549755813888",
"1099511627776","2199023255552","4398046511104","8796093022208",
"17592186044416","35184372088832","70368744177664","140737488355328",
"281474976710656","562949953421312","1125899906842624",
"2251799813685248","4503599627370496","9007199254740992",
"18014398509481984","36028797018963968","72057594037927936",
"144115188075855872","288230376151711744","576460752303423488",
"1152921504606846976","2305843009213693952","4611686018427387904","9223372036854775808"};
//判断子序列长度
int pend(string a, string b){
int p = 0;
for(int i = 0; i < a.length(); i++){
if(a[i] == b[p]){
p++;
}
if(p == b.length()){
break;
}
}
return p;
}
int judge(string a){
int ans = 100;
for(int i = 0; i < 65; i++){
int tmp = pend(a, ex[i]);
ans = min(ans, (int)((a.length() - tmp) + (ex[i].length() - tmp)));
}
return ans;
}
void solve(){
string a;
cin >> a;
cout << judge(a) << endl;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("1.in","r",stdin);
#endif
int tt;
cin >> tt;
while(tt--){
solve();
}
return 0;
}
坑点
这道题目没有给出k的范围,导致很容易想当然的认为 0 ≤ k ≤ 32 0≤k≤32 0≤k≤32,实际上由于可以往n末尾添加数字,k可以达到60。