锐评一下

做的是非常差劲了,这还是我选的简单一点的div2版本,不知道是因为洛谷的题偏难还是就是我自己的原因,第一题签到做了得有20分钟了,后面看了半个多小时第二题做不出来,第一题的hard版本光看题目就把我劝退了,革命尚未成功,同志仍需努力。

「CROI · R2」在相思树下 I

题目描述

本题采用多组数据测试。

现在欣欣有一个从 1n 的序列,并想对这个序列进行如下两种操作。

操作一:删去所有的奇数项。

操作二:删去所有的偶数项。

欣欣发现她在进行 k 次操作后,最后只剩下一个数,但她不知道这个数是多少,于是欣欣来找你求助,她会给你她所进行的 k 次操作的种类,希望你告诉她最后的那个数是多少。

输入格式

第一行一个正整数 T,表示数据组数。

对于每组数据:

第一行两个整数 nk,含义如题面所示。

第二行 k 个整数,代表欣欣依次进行的操作种类,其中 1 代表操作一,2 代表操作二。

输出格式

T 行,每行一个数代表每组数据对应的答案。

样例 1

样例输入 1

4
5 2
1 1
8 3
2 2 2 
8 3 
1 1 1
8 3
1 2 1

样例输出 1

4
1
8
6

提示

【样例解释】

对于第一组数据,序列的变化如下:

\{1,2,3,4,5\} \to \{2,4\} \to \{4\}

【数据范围】

对于 30\% 的数据, n\le 5\times10^5

对于 100\% 的数据,1\le T \le 101\le n\le 10^{18}

保证对于所有的数据,操作 k 次后均仅剩下一个数。

思路

  • 想思路的时候都想了很久,模拟了一下感觉不是这么简单,所以打表也不成。
  • 后来找规律,错了一次,但也接近正确答案了,又推了一下,发现每次不管是去除奇数项还是偶数项,相邻两个数之间的距离都会放大一倍,所以就比较显然了,初始值设为第一项,如果后面去除了奇数项,那么第一项加上距离差就会变成下一项,成为新的第一项。
  • 我先判断第一项是去除奇数项还是偶数项,用来确定我初始值是1还是2,随后从第二项开始枚举,如果是1则让结果加上距离差,然后每一次距离差都乘2.
// Problem: T449099 「CROI · R2」在相思树下 I
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/T449099?contestId=178774
// Memory Limit: 512 MB
// Time Limit: 1000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include<bits/stdc++.h>
using namespace std;
using ll = long long;
const int N = 1e5 + 9;
#define int long long
const int MOD = 998244353;
int qmi(int a, int b, int p) {
	int res = 1;
	while (b) {
		if (b & 1) res = res * a % p;
		a = a * a % p;
		b >>= 1;
	}
	return res;
}
int inv(int x) {return qmi(x, MOD - 2, MOD);}

int gcd(int a, int b) {return b > 0 ? gcd(b, a % b) : a;}
int lcm(int a, int b) {return a / gcd(a, b) * b;}

int n, k, a[N];

void solve() {
	cin >> n >> k;
	for (int i = 1; i <= k; ++ i) cin >> a[i];
	int ans;
	if (a[1] == 1)ans = 2;
	else ans = 1;
	int dif = 2;

	for (int i = 2; i <= k; ++ i) {
		if (a[i] == 1) ans += dif;
		dif *= 2;

	}
	cout << ans << "\n";
}

signed main() {
	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
	int _ = 1;
	cin >> _;
	while (_--) solve();
	return 0;
}