https://www.luogu.com.cn/problem/P10765
题目描述
本题采用多组数据测试。
现在欣欣有一个从 \(1\) 到 \(n\) 的序列,并想对这个序列进行如下两种操作。
操作一:删去所有的奇数项。
操作二:删去所有的偶数项。
欣欣发现她在进行 \(k\) 次操作后,最后只剩下一个数,但她不知道这个数是多少,于是欣欣来找你求助,她会给你她所进行的 \(k\) 次操作的种类,希望你告诉她最后的那个数是多少。
输入格式
第一行一个正整数 \(T\),表示数据组数。
对于每组数据:
第一行两个整数 \(n\) 和 \(k\),含义如题面所示。
第二行 \(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 10\),\(1\le n\le 10^{18}\)。
保证对于所有的数据,操作 \(k\) 次后均仅剩下一个数。
分析:
1.首先,开始向正确思路发展的第一步是:想到了,到最后第一个没有被划掉的数字,就是我们要找的答案。
2.第二个接近正确思路的是,公差每次*2。比如,操作是1,则划掉1,3,5,7....公差2
第二次操作还是1,划掉2,6,10,14....公差4
第三次操作是2,划掉8,16 ... 公差8
3.接下来,就没有直击正解了,每次都想先划掉谁。看题解,是每次先保留谁(思维正反面)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
操作1:
2 4 6 8 10 12 14 16 18
操作2:
2 6 10 14 18
操作2:
2 10 18
得到结论:操作2照此下去,会发现首个数字不变。
操作1:
10
会发现,首个数字+公差
所以,每次,求出首个数字是关键。得到结论:
如果是操作1,上一轮的首个数字+公差。
如果是操作2,上一轮的首个数字还是这一轮的首个数字。
#include<bitsstdc++.h>
#define ll long long
using namespace std;
ll n,m,t;
int p;
int main(){
cin>>t;
while(t--){
cin>>n>>m;
ll a = 1, d = 1;
for(int i = 1; i <= m; i++){
cin>>p;
if(p == 1){
a = a + d;
}
d *= 2;
// cout<<"a:"<<a<<endl;
}
cout<<a<<endl;
}
return 0;
}