好久没写博客啦~以后还得坚持下去啊!
今天做了牛客的小白月赛31,我的天,竟然忽略了多个测试组时,在每组开始时把状态数组重新初始化的事....导致我一道题一直WA。。
长记性了,以后一定不会错的!!!
话不多说,上题!
A题 A|B
题目链接:https://ac.nowcoder.com/acm/contest/10746/A
思路:
这道题因为a <= 10^9 , 所以a的位数最多是31位(因为2^30 == 10^9),因此遍历的时候i从30~0进行遍历。
b的个数取决于a的各位的0的个数,但是自己的实现方法太粗糙了,参考了大佬的代码,优美版AC代码如下:
#include<bits/stdc++.h>
using namespace std ;
long long sum;
int cnt[40];
int res ;
int main(){
int t , a , x;
cin >> t;
while(t --){
sum = 0;
scanf("%d%d",&a,&x);
for(int i = 30 ; i >= 0 ; i --){
if(a & (1 << i)) cnt[i] = 1;
else {
cnt[i] = 0;
res ++;
}
}
int b = 0;
for(int i = 30 ; i >= 0 ; i --){
if(cnt[i]) continue;
if(b + (1 << i) <= x){
b += (1 << i); //只要a的这位为0,并且b + (1 << i)的和 <=x , 那么在这位上b就可以取到0或1,即:加上2^i
sum += (1 << (res - 1)); //比如a有四位,分别是0001,这个res = 3 ,在对最高位考虑之后,b最高位数定下,然后剩下两个0(res - 1),分别可以取0或1,所以sum += 1 << (res - 1)
}
res --; //每次把对应的b的位定了之后,a的0的数量减1
}
printf("%lld
",sum);
}
return 0;
}
G题 简单题的逆袭
题目链接:https://ac.nowcoder.com/acm/contest/10746/G
思路:
这道题就是暴力 + 枚举,可以知道当x == 1 || x == 0 || y == 0时,输出-1 , 当y == 1时,输出 0(在这里0^0 = 1)
在这里的难点是使用__uint128_t 表示128位无符号整数来完成大数的乘法 , 只要结果 <= y , 就把结果加1。
这里有个小疑问 , 就是不知道为什么不能把x ^ k <= y 两边以x为底取对数 , 然后再利用换底公式转变为 k <= log2(y) / log2(x) , 下面也将会贴上这个疑惑代码。
AC代码:
#include<bits/stdc++.h>
using namespace std;
int main(){
long long x , y;
int t ;
long long k;
__uint128_t xx , yy;
cin >> t;
while(t --){
scanf("%lld %lld",&x,&y);
xx = x , yy = y;
if((xx == 1) || (yy == 0 ) || (xx == 0 ) ) printf("-1
");
else if(yy == 1) printf("0
");
else{
int ans = 0;
__uint128_t p = 1;
while(p * xx <= yy){
ans ++;
p *= xx;
}
cout << ans << endl;
}
}
return 0;
}
疑惑代码:
#include<bits/stdc++.h>
using namespace std;
int main(){
long long x , y;
int t ;
long long k;
cin >> t;
while(t --){
scanf("%lld %lld",&x,&y);
if((x == 1) || (y == 0 ) || (x == 0 ) ) printf("-1
");
else if(y == 1) printf("0
");
else{
k = (long long)log2(y) / log2(x);
printf("%lld
",k);
}
}
return 0;
}
H题 对称之美
题目链接:https://ac.nowcoder.com/acm/contest/10746/H
思路:
这道题说白了就是模拟题,只要把数组的边界考虑好就可,在此切记!!,每重新开始一组测试数据,一定要把flag数组和string数组重新初始化,不然!!后果很严重(WA。。。
此外没什么好说的了,AC代码如下:
#include<bits/stdc++.h>
using namespace std;
int n;
int flag[110];
int main(){
int t;
cin >> t;
while(t --){
memset(flag , 0 , sizeof flag);
string s[110];
scanf("%d",&n);
for(int i = 0 ; i < n ; i ++) cin >> s[i];
if(n == 1){
puts("Yes");
}
else{
for(int i = 0 ; i <= (n - 1) / 2 ; i ++){
int len1 = s[i].length();
int len2 = s[n - i - 1].length();
for(int j = 0 ; j < len1 ; j ++){
for(int k = 0 ; k < len2 ; k ++){
if(s[i][j] == s[n - i - 1][k]) {
flag[i] = 1;
}
}
}
}
}
int temp = 1 ;
for(int i = 0 ; i <= (n - 1) / 2 ; i ++){
if(flag[i] != 1) temp = 0;
}
if(temp && n != 1) puts("Yes");
else if(temp == 0 && n != 1) puts("No");
}
return 0;
}
I题 非对称之美 题目链接:https://ac.nowcoder.com/acm/contest/10746/I
思路:
这道题首先考虑是否存在所有字符都相同的情况,如果存在,则最长非回文字符串长度是 0;
反之,接着考虑以下两点:
1.分别比较从第一个字符到最中间的字符是否和其对应位置的字符相同,若至少存在一处不同,则最长非回文字符串长度是 len,即字符串总长度;
2.如果每个字符都和其对应位置的字符相同,那么最长非回文字符串长度是 (len - 1)即(字符串总长度 - 1) ; (因为先前已经排除了所有字符都相同的情况发生)
AC代码:
#include<bits/stdc++.h>
using namespace std;
int main(){
string s;
cin >> s ;
int res = 1 ;
int len = s.length();
for(int i = 0 ; i < len - 1 ; i ++){
if(s[i] != s[i + 1]){
res = 0;
break;
}
}
if(res) printf("0"); //排除所有字符相等情况
else{
int ans = 1; //如果所有对应位置的字符都相等,则最长非回文字符串是len - 1
for(int i = 0 ; i <= (len - 1) / 2 ; i ++){
if(s[i] != s[len - i - 1]){ //只要有对应位置不相等的字符,则最长非回文字符串是len
ans = 0;
break;
}
}
cout << len - ans ;
}
return 0;
}
这次的牛客小白月赛让我意识到了我是有多菜,还要继续加油呀~
另外特别感谢赛后帮我一起debug的小李同学~~~~