原文链接https://codeforces.com/problemset/problem/1560/D
制作不易,你的关注和点赞是我CF之路的不懈动力,加油,陌生人
D. Make a Power of Two
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output
You are given an integer nn. In 11 move, you can do one of the following actions:
- erase any digit of the number (it's acceptable that the number before the operation has exactly one digit and after the operation, it is "empty");
- add one digit to the right.
The actions may be performed in any order any number of times.
Note that if, after deleting some digit from a number, it will contain leading zeroes, they will not be deleted. E.g. if you delete from the number 301301 the digit 33, the result is the number 0101 (not 11).
You need to perform the minimum number of actions to make the number any power of 22 (i.e. there's an integer kk (k≥0k≥0) such that the resulting number is equal to 2k2k). The resulting number must not have leading zeroes.
E.g. consider n=1052n=1052. The answer is equal to 22. First, let's add to the right one digit 44 (the result will be 1052410524). Then let's erase the digit 55, so the result will be 10241024 which is a power of 22.
E.g. consider n=8888n=8888. The answer is equal to 33. Let's erase any of the digits 88 three times. The result will be 88 which is a power of 22.
Input
The first line contains one integer tt (1≤t≤1041≤t≤104) — the number of test cases. Then tt test cases follow.
Each test case consists of one line containing one integer nn (1≤n≤1091≤n≤109).
Output
For each test case, output in a separate line one integer mm — the minimum number of moves to transform the number into any power of 22.
Example
input
Copy
12 1052 8888 6 75 128 1 301 12048 1504 6656 1000000000 687194767
output
Copy
2 3 1 3 0 0 2 1 3 4 9 2
Note
The answer for the first test case was considered above.
The answer for the second test case was considered above.
In the third test case, it's enough to add to the right the digit 44 — the number 66 will turn into 6464.
In the fourth test case, let's add to the right the digit 88 and then erase 77 and 55 — the taken number will turn into 88.
The numbers of the fifth and the sixth test cases are already powers of two so there's no need to make any move.
In the seventh test case, you can delete first of all the digit 33 (the result is 0101) and then the digit 00 (the result is 11).
------------------------------------------------------------------------------------------------------------------------
题目要求把给定数字改写成2^k次幂形式,直接对n操作是非常麻烦,毫无规律可循的。
由于在范围内的2的k次幂就那么几个,我们可以对结果进行枚举;
两个操作,一个删除,一个末尾增加,显然为了让操作次数少,把从目标数字最前面开始连续的,相等的部分留下来,其余全部删除,然后末尾补上缺的。
比如1024 17808472-》 17808472 因为我们补数只能从最后面补,所以我们应该最大化利用现存的。 有没有可能先补后删会更优?不可能,先补只能在最末尾补,补也是从目标数第一个位补,这样删的话删的更多。
把数字转化成字符串,对于每个目标串,按照从开头到末尾的顺序,寻找上面红色的部分,记录长度,运算即可。
# include<iostream>
# include<algorithm>
# include<math.h>
# include<cstring>
using namespace std;
#define N 100010
typedef long long int ll;
string s[100];
int main()
{
int t;
cin>>t;
ll ans=1;
for(int i=1;ans<=1e18;i++)
{
ll x=ans;
while(x)
{
int now=x%10;
s[i]=char(now+'0')+s[i];
x/=10;
}
ans*=2;
}
while(t--)
{
int n;
cin>>n;
string t="";
int m=n;
while(m)
{
int now=m%10;
t=char(now+'0')+t;
m/=10;
}
int ans=999999;
for(int i=1;i<=60;i++)
{
string now=s[i];
int qian=0;
for(int j=0;j<t.length();j++)
{
if(t[j]==now[qian])
{
qian++;
}
}
int hou=s[i].length()-qian;
int len=t.length();
ans=min(ans,len-qian+hou);
}
cout<<ans<<'\n';
}
return 0;
}