# Getting Zero
## 题面翻译
给定 $v$,可以将 $v$ 如下操作:
变成 $(v + 1) \% 32768$ 或者 $2\times v\%32768$,
求最少经过几次操作能将 $v$ 变回 $0$。
## 题目描述
Suppose you have an integer $ v $ . In one operation, you can:
- either set $ v = (v + 1) \bmod 32768 $
- or set $ v = (2 \cdot v) \bmod 32768 $ .
You are given $ n $ integers $ a_1, a_2, \dots, a_n $ . What is the minimum number of operations you need to make each $ a_i $ equal to $ 0 $ ?
## 输入格式
The first line contains the single integer $ n $ ( $ 1 \le n \le 32768 $ ) — the number of integers.
The second line contains $ n $ integers $ a_1, a_2, \dots, a_n $ ( $ 0 \le a_i < 32768 $ ).
## 输出格式
Print $ n $ integers. The $ i $ -th integer should be equal to the minimum number of operations required to make $ a_i $ equal to $ 0 $ .
## 样例 #1
### 样例输入 #1
```
4
19 32764 10240 49
```
### 样例输出 #1
```
14 4 4 15
```
## 提示
Let's consider each $ a_i $ :
- $ a_1 = 19 $ . You can, firstly, increase it by one to get $ 20 $ and then multiply it by two $ 13 $ times. You'll get $ 0 $ in $ 1 + 13 = 14 $ steps.
- $ a_2 = 32764 $ . You can increase it by one $ 4 $ times: $ 32764 \rightarrow 32765 \rightarrow 32766 \rightarrow 32767 \rightarrow 0 $ .
- $ a_3 = 10240 $ . You can multiply it by two $ 4 $ times: $ 10240 \rightarrow 20480 \rightarrow 8192 \rightarrow 16384 \rightarrow 0 $ .
- $ a_4 = 49 $ . You can multiply it by two $ 15 $ times.
思路:
贪心思想,有两条路可走,那么将这两条路拆开分析,第一条路,直接加一;第二条路,直接乘以二。在mod上考虑我们发现,32768为2的15次方,那么看第二条路我们发现是直接增加2的因子数,最多15次就能倍32768整除,也就变成了k*2的次方形式,mod后得k,最多不超过15次;那么由此看第一条路。我们发现是为了增加2的因子数才使用这条路,因为1到32768的数中包含2的次方数不同,进而我们使用打表的方法,预处理出1到32768的所有2的因子数,再进行遍历,注意,因为我们的次数最多不超过15次,所以只遍历15次即可。别忘了取mod。
AC代码如下:
// 蓝桥杯.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <iostream>
#include <algorithm>
#include <cmath>
#include<vector>
#include <string>
using namespace std;
int pan2(int num)
{
int c;
if (num == 0) c = 15;
else c = log2(num&(-num));
return c;
}
int l1(int num)
{
return (15-pan2(num));
}
int l2(int num, int* a)
{
int min = 1000000;
int c = 0;
for (int i = 1; i <= 15; i++)
{
c++;
if (min > 15 - a[i + num] + c) min = 15 - a[i + num] + c;
}
return min;
}
int main()
{
int t;
t = 1;
while (t--)
{
int n;
cin >> n;
int a[33000] = { 0 };
for (int i = 1; i <= 33000; i++)
{
a[i] = pan2(i);
}
for (int i = 0; i < n; i++)
{
int c1 = 0;
int c2 = 0;
int num;
cin >> num;
num = num % 32768;
c1 = l1(num);
c2 = l2(num,a);
cout << min(c1, c2)<<' ';
}
}
return 0;
}