A题传送门
从这次开始不放原题了。
题目大意:
寻找一个最大的数字t<=x,使给定的x做x&(x-1)&…&t=0
解题思路:
思考&运算的特点,这位上有一个0,那么结果相应的位上就是0,那么思考一下最难变成0的位是哪个,很明显,一定是最高位的1,那么我们要把它变成0,并且还需要最大值,那么最后的答案一定形如01111…111这样的数字,也就是我们只需要把原数字x的位数求出来,最后的答案就是2^(cnt-1) - 1.
代码如下:
#include<iostream>
#include<cstring>
#include<algorithm>
#include<stack>
using namespace std;
int pow_mod(int a, int n)
{
long long ans = 1;
while (n) {
if (n & 1) {
ans = (ans * a);
}
a = (a * a);
n >>= 1;
}
return ans;
}
int main()
{
int t;
cin >> t;
while (t--)
{
stack<int>st;
int x;
cin >> x;
int cnt=0;
while (x)
{
x >>= 1; cnt++;
}
cout << pow_mod(2, cnt-1) - 1<<endl;
}
return 0;
}
B1题传送门
目前只会简单版本
题目大意:
给定一个只含01的回文串,两种操作,第一种花一块钱把0变成1,第二种不花钱,但是要求串不能回文并且上一次操作不能是翻转,翻转整个字符串。
A先B后,询问最优策略下谁赢。
解题思路:
一般情况下,A一开始不能翻转,不考虑特殊情况下,只能把0变成1,就会变成非回文串,B每次都只需要将对称的0变成1,然后B只要等到剩下最后一对0的时候,进行翻转,不出意外就会少花2块钱,B赢。
特殊情况1:
没有0,直接平局。
特殊情况2:
A把0变成1的时候,并没有把串变成非回文串,也就是串是奇数长度,并且中间是0,这样A就反客为主,多花一块钱,然后反杀B2块钱,所以A赢。
所以代码如下:
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
int main()
{
int t;
cin >> t;
while (t--)
{
int len;
string s;
cin >> len >> s;
int cnt0 = 0;
for (int i = 0; i < len; ++i)
{
cnt0 += s[i] == '0';
}
if (cnt0 == 0)cout << "DRAW" << endl;
else if (cnt0==1||cnt0%2==0)cout << "BOB" << endl;
else cout << "ALICE" << endl;
}
return 0;
}
C题传送门
题目大意
求
解题思路:
待续
代码如下:
#include<iostream>
#include<cstring>
#include<algorithm>
#include<map>
using namespace std;
long long x[100050];
int main()
{
int t; cin >> t;
while (t--)
{
long long ans = 0;
map<int, long long>m;
int n; cin >> n;
for (int i = 1; i <= n; i++)
cin >> x[i];
for (int i = 1; i <= n; ++i)
{
ans += (0ll+n - i + 1) * m[x[i]];
m[x[i]] += i;
}
cout << ans << endl;
}
return 0;
}