这一题其实很简单,只是要想到正确方法
我一开始用了奇怪的搜索
①无解的情况:
看上去很离奇,实际上略加思索就会发现,如果输入 n n n 为偶数,那么就铁定无解。证明过程如下:
令
n
m
o
d
2
=
0
n\bmod{2}=0
nmod2=0,人距离
n
n
n 点的距离为
d
i
s
dis
dis ,则当走出第一步(步长为
1
1
1)时,有:
d
i
s
=
∣
n
±
1
∣
dis=\mid n\pm1\mid
dis=∣n±1∣
所以:
d
i
s
≡
1
(
m
o
d
i
)
dis\equiv1\pmod{i}
dis≡1(modi)
设
k
k
k 为正整数且满足
k
>
1
k > 1
k>1 ,显然有:
2
k
≡
0
(
m
o
d
2
)
2^k \equiv0\pmod{2}
2k≡0(mod2)
因此,在走出第一步后无论怎么走也到达不了奇数的距离,即无法走到
n
n
n 点。
②有解的情况
似乎是一道走路问题,实际上我们可以把向左走看成减法,把向右走看成加法,那么题目就转化成了:
有一个正整数 n n n,试回答 n n n 是否满足如下式子:
n = ⋆ 2 0 ⋆ 2 1 ⋆ . . . . . . ⋆ 2 k n=\star2^0\star2^1\star......\star2^k n=⋆20⋆21⋆......⋆2k
如果不满足,则输出 − 1 -1 −1,否则输出 k k k ( k ∈ N + ) (k\in \mathbb N_+) (k∈N+),其中" ⋆ \star ⋆"处可以填正号或负号使式子成立
那么我们观察数据,手算几个,就可以发现:
1
=
2
0
1=2^0
1=20
3
=
2
0
+
2
1
3=2^0+2^1
3=20+21
5
=
−
2
0
+
2
1
+
2
2
5=-2^0+2^1+2^2
5=−20+21+22
.
.
.
.
.
.
......
......
规律很难找,但是我们发现不管怎么样,都有
n
≤
∣
⋆
2
0
∣
+
∣
⋆
2
1
∣
+
.
.
.
.
.
.
+
∣
⋆
2
k
∣
n\le\mid\star2^0\mid+\mid\star2^1\mid+......+\mid\star2^k\mid
n≤∣⋆20∣+∣⋆21∣+......+∣⋆2k∣, (“
⋆
\star
⋆"意义如上所述),这其实很好解释,因为如果不满足这个关系式,那么就算”
⋆
\star
⋆"处全部使用正号,也无法达到
n
n
n 的值。
所以我们便可以利用这个特性,让一个变量
t
o
t
tot
tot 每次累加
2
i
2^i
2i ,直到
t
o
t
≥
n
tot\ge n
tot≥n,此时累加的次数就是答案。
CODE(这里提供三份代码):
def main():
T = int(input())
for k in range(T + 1):
n = int(input())
if not (n & 1):
print(-1)
continue
tot = 0
for i in range(0, 114514):
tot += (1 << i)
if tot >= n:
print(i + 1)
#注意这里由于i从0开始,所以输出i+1
break
if __name__ == '__main__':
main()
#include <stdio.h>
int main() {
int T, n, tot = 0;
scanf("%d", &T);
while(T --) {
scanf("%d", &n);
if(! (n & 1)) {
printf("-1\n");
continue;
}
for(int i = 0; ; i += 1) {
tot += (1 << i);
if(tot >= n) {
printf("%d\n", i + 1);
break;
}
}
tot = 0;
}
return 0;
}
#include <bits/stdc++.h>
#define endl '\n'
using namespace std;
int T, n;
int tot = 0;
signed main() {
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
cin >> T;
while(T --) {
cin >> n;
if(! (n & 1)) {
cout << -1 << endl;
continue;
}
for(int i = 0; ; i ++) {
tot += (1 << i);
if(tot >= n) {
cout << i + 1 << endl;
break;
}
}
tot = 0;
}
return 0;
}