一开始写的代码如下:
#include <bits/stdc++.h>
using namespace std;
int main(){
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int n, k; cin >> n >> k;
vector<int> a(n + 1);
for (int i = 1; i <= n; i++) cin >> a[i];
int flag = 0; //判断是谁拿
int alice = 0, bob = 0;
for (int i = 1; i <= n; i++) {
while (a[i]) {
int m = 0;
if (k != 1) { //k等于1的时候下面的while循环无法跳出
while (pow(k, m) <= a[i]) m++;
m--;
}
a[i] -= pow(k, m);
if (flag == 0) {
alice++;
flag = 1;
}
else {
bob++;
flag = 0;
}
}
}
if (alice == bob) cout << "Bob" << endl;
else cout << "Alice";
return 0;
}
检测的结果如上……(心碎)
原来的代码确实时间复杂度很高,最惨的时候大约要跑2e12次,所以不负众望的挂了。
看出挨个遍历一遍数组a,然后一步一步找合适的指数的方法,显然是不行了。
于是!我去看了答案……答案给出的方法十分巧妙,总之是我想不到的……
应为k肯定为一个奇数,所以每人一次拿走的饼干数量k^m一定是奇数。而这个是奇数就决定了,如果a为奇数,则一定要拿奇数次,如果a为偶数,就一定会拿偶数次。
这里要先知道一点,就是如果拿了奇数次,则最后一次一定是Alice拿(因为Alice是先手),要是偶数次,就一定是Bob拿。
记flag = 0表示下一次是Alice拿,flag = 1表示下一次是Bob拿。
所以只要挨个遍历一遍数组a,如果a为奇数,就令flag = 1,若为偶数,令flag = 0。以此类推,最后根据相反的flag判断赢的是谁。
#include <bits/stdc++.h>
using namespace std;
int main(){
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int n, k; cin >> n >> k;
vector<int> a(n + 1);
for (int i = 1; i <= n; i++) cin >> a[i];
int flag = 0; //判断是谁拿
for (int i = 1; i <= n; i++) {
if (flag == 0) {
if (a[i] % 2 == 0) flag = 0;
else flag = 1;
}
else {
if (a[i] % 2 == 0) flag = 1;
else flag = 0;
}
}
if (flag == 0) cout << "Bob" << endl;
else cout << "Alice";
return 0;
}