A. ABC
题目大意:
思路:
有这么几种情况
- 字符串大小为1,此时无法获得长度大于1的回文子串
- 字符串的大小大于3,此时无论怎么排,都会出现"11",“00”,“101”,"010"这样的回文子串
- 长度为2,只有"11","00"是回文子串
代码:
void work()
{
string s;
int n;
cin >> n;
cin >> s;
if (s.size() == 1)
{
cout << "YES" << endl;
return;
}
if (s.size() >= 3)
{
cout << "NO" << Endl;
return;
}
if (s == "11" || s == "00")
cout << "NO" << Endl;
else
cout << "YES" << Endl;
}
B. Roof Construction
题目大意:
思路:
从位运算的角度看,我们可以发现在最高位相同的情况下,xor的最大值没有最高位不同的两数xor值大,
而且,我们发现必然有两个最高位不同的数排在一起,我们使用0和最高位为1的最小的数拍在一起,此时成本为2^x,成本最低,其他的数按顺序拍到两侧即可
代码:
void work()
{
cin >> n;
int cnt = 1;
while (cnt * 2 < n)
cnt *= 2;
for (int i = cnt-1; i >= 0; i--)
cout << i << " ";
for (int i = cnt; i < n; i++)
C. Strange Test
题目大意:
思路:
我们知道操作3能够使a,b接近的更多,对于最后一次操作前的a,b,记作a1,b1
总代价:(a1-a)+(b1-b) + ((a1|b1) - b1) + 1 = a1 + (a1|b1) + (1 - a - b)
已知(1-a-b)的代价固定,我们需要做的就是使a1+(a1|b1)最小
我们可以枚举a1,从位运算的角度从高到低考虑
- 如果 a1 为0 b 为1 则 b1 设置为 1
- 如果 a1 为0 b 为0 则 b1 设置为 0
- 如果 a1 为0 b 为1 则 b1 设置为 1
- 如果 a1 为0 b 为0 则 b1 设置为 1 并停止,此时b需要通过操作2来到b1,最劣情况,因此停止
之后计算代价即可
代码:
void work()
{
cin >> a >> b;
int ans = b - a;
for (int a1 = a; a1 < b; a1++)
{
int b1 = 0;
for (int i = 23; i >= 0; i--)
{
if (b & (1 << i))
b1 = b1 | (1 << i);
else
{
if (a1 & (1 << i))
{
b1 = b1 | (1 << i);
break;
}
}
}
ans = min(ans, a1 - a - b + (a1 | b1) + 1);
}
cout << ans << endl;
}
D. New Year Concert
题目大意:
思路:
可以发现gcd(1-n)的值是递减的,
如果我们固定l,可以通过二分的方法找到l,r,使得[l,r]为不满足区间
对于一个不满足区间,我们可以更改其中一个数为质数,是的该区间和包含它的区间满足
因此,我们可以枚举l,得到所有不满足区间,之后使用贪心解决这个区间覆盖问题
我们可以使用线段树来快速得到区间的gcd
代码:
cin >> n;
nums.resize(n + 1);
for (int i = 1; i <= n; i++)
cin >> nums[i];
build(1, 1, n);
for (int i = 1; i <= n; i++)
{
int nowL = i + 1;
int nowR = n;
int ans = i;
while (nowL <= nowR)
{
int nowMid = (nowL + nowR) / 2;
if (query(1, 1, n, i, nowMid) >= nowMid - i + 1)
{
ans = nowMid;
nowL = nowMid + 1;
}
else
nowR = nowMid - 1;
}
// cout << i << " " << ans << endl;
if (query(1, 1, n, i, ans) == ans - i + 1)
segs[ans].push_back(i);
}
int nowPos = 0;
for (int i = 1; i <= n; i++)
{
for (int it : segs[i])
{
// cout << i << " " << it << endl;
if (it > nowPos)
{
ans++;
nowPos = i;
}
// cout << nowPos << " " << ans << endl;
}
cout << ans << " ";
}