洛谷 P8918 『MdOI R5』Jump 题解

发布时间 2023-04-02 09:57:15作者: ZyIOLO

题目传送门

这一题其实很简单,只是要想到正确方法

我一开始用了奇怪的搜索

①无解的情况:

看上去很离奇,实际上略加思索就会发现,如果输入 \(n\) 为偶数,那么就铁定无解。证明过程如下:

\(n\bmod{2}=0\),人距离 \(n\) 点的距离为 \(dis\) ,则当走出第一步(步长为 \(1\))时,有:

\[dis=\mid n\pm1\mid \]

所以:

\[dis\bmod{i} = 1 \]

\(k\) 为正整数且满足 $k > 1 $ ,显然有:

\[2^k \bmod{2}=0 \]

因此,在走出第一步后无论怎么走也到达不了奇数的距离,即无法走到 \(n\) 点。

②有解的情况

似乎是一道走路问题,实际上我们可以把向左走看成减法,把向右走看成加法,那么题目就转化成了:

有一个正整数 \(n\),试回答 \(n\) 是否满足如下式子:

\[n=\star2^0\star2^1\star......\star2^k \]

如果不满足,则输出 \(-1\),否则输出 \(k\) \((k\in N_+)\),其中"\(\star\)"处可以填正号或负号使式子成立

那么我们观察数据,手算几个,就可以发现:

\[1=2^0 \]

\[3=2^0+2^1 \]

\[5=-2^0+2^1+2^2 \]

\[...... \]

规律很难找,但是我们发现不管怎么样,都有 $n\le\mid\star20\mid+\mid\star21\mid+......+\mid\star2^k\mid \(, ("\)\star\("意义如上所述),这其实很好解释,因为如果不满足这个关系式,那么就算"\)\star$"处全部使用正号,也无法达到 \(n\) 的值。
所以我们便可以利用这个特性,让一个变量 \(tot\) 每次累加 \(2^i\) ,直到 \(tot\ge 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;
}