C.异或故事(位运算, 范围)
只过了60%的代码:原因在于最后为了确保b和c不为0的时候,选择了在最高位的上面一位给b和c都加上1,这实际上会有溢出的风险,被卡掉了。
#include<iostream>
#define int long long
using namespace std;
int T;
signed main() {
cin >> T;
while (T --) {
int a, b = 0, c = 0;
cin >> a;
int idx = 0;
bool turn = 1;
// 处理 a == 1 的特殊情况
if (a == 1) {
cout << 2 << " " << 3 << endl;
continue;
}
// 普通情况,交替分配位给 b 和 c
while (a) {
if ((a & 1) == 1) {
if (turn)
b |= (1 << idx);
else
c |= (1 << idx);
turn = !turn;
}
idx++;
a >>= 1;
}
// 确保 b 和 c 都不为 0
if (b == 0 || c == 0) {
b |= (1 << idx);
c |= (1 << idx);
}
cout << b << " " << c << endl;
}
return 0;
}
AC代码一:思路与我类似,1e9对于二进制最高有32bit,对于a的二进制为1的位置上,设置一个turn变量,b和c依次轮流为1,让b和c尽可能接近,不要超过1e9的范围。由于b是第一个设置1的数,所以只有c可能会是0,这里做法不是在最高位的上一位将b和c修改为1,而是找到a最低的0位,将b和c对应位置同时改为1。
#include<iostream>
using namespace std;
int T;
int main(){
cin >> T;
while (T --){
int a, b = 0, c = 0; cin >> a;
bool turn = 1;
for(int i = 0; i < 32; i ++){
if((a >> i) & 1){
if(turn) b |= (1 << i);
else c |= (1 << i);
turn = !turn;
}
}
if (c == 0)
for(int i = 0; i < 32; i ++){
if(((a >> i) & 1) == 0){ // 这边注意==的优先级比&更大
b |= (1 << i);
c |= (1 << i);
break;
}
}
cout << b << " " << c << endl;
}
return 0;
}
AC代码二:利用异或性质,a ^ b = c ====> a ^ c = b,那么只需要考虑三种情况即可,a = 1时,输出2和3;对于a = 1e9,输出3000和1e9^3000的结果即可(如果为1的话,异或的另一边会超出1e9);其他情况直接输出1和1^a结束。
#include<iostream>
using namespace std;
const int N = 1e9;
int T;
int main(){
cin >> T;
while (T --){
int a, b = 0, c = 0; cin >> a;
if(a == 1) cout << 2 << " " << 3 << endl;
else if (a == N) cout << 4000 << " " << (N ^ 4000) << endl;
else cout << 1 << " " << (1 ^ a) << endl;
// 注意异或运算符优先级是大于 <<的
}
return 0;
}
E.约会故事(大模拟)
思路:
①一开始写代码写复杂了(时和分钟分开来进行了比较,导致处理比较繁琐),最简单的方式应该全部转化为分钟去处理。
②注意给定的快乐时间,题目中没有说一定是在同一天,所以可能出现快乐开始时间大于结束时间的情况,这时候要考虑到第二天。
③某个区间都是快乐的,给定起止区间====>利用差分和前缀和简化。注意隔天快乐的设置的方法。
代码:
#include<iostream>
#include<unordered_map>
#include<unordered_set>
using namespace std;
int happy[1500]; // 60 * 24 = 1440 定义为差分数组
unordered_set<string> ld;
int cal(string time){ // 转化为分钟数
int h = (time[0] - '0') * 10 + (time[1] - '0');
int m = (time[3] - '0') * 10 + (time[4] - '0');
return h * 60 + m;
}
int main(){
int n, m; cin >> n >> m;
for(int i = 0; i < n; i ++){
string st, ed; cin >> st >> ed;
int stmin = cal(st), edmin = cal(ed);
if(stmin == edmin) happy[0] += 1000; // 后面求前缀和就可以全部置为happy(true)了
else if(stmin > edmin){ // 隔天
happy[stmin] += 1, happy[0] += 1, happy[edmin + 1] -= 1;
}else
happy[stmin] += 1, happy[edmin + 1] -= 1;
}
for(int i = 1; i < 120; i ++) happy[i] += happy[i - 1]; // 求前缀和数组
for(int i = 0; i < m; i ++){
string d; cin >> d;
ld.insert(d);
}
int ty; cin >> ty;
while (ty --){
string tytime, xqqtime, ctime;
cin >> tytime >> xqqtime >> ctime;
int x1 = cal(tytime);
int xqqmin = cal(xqqtime), cmin = cal(ctime);
string tea; cin >> tea;
//cout << (xqqmin < cmin) << endl;
if(x1 < 120 && happy[x1] && ld.count(tea) && xqqmin <= cmin) cout << "Winner xqq" << endl;
else if(x1 > 120 || !happy[x1]) cout << "Loser xqq" << endl;
else if(x1 < 120 && happy[x1] && (ld.count(tea) == 0 || xqqmin > cmin))
cout << "Joker xqq" << endl;
}
return 0;
}