题目链接:https://codeforces.com/contest/1789
解题思路:找到两个gcd小于等于2的放到前面,就可以了
#include<bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f3f
#define lson l,mid,rt<<1
#define rson mid+1,r,(rt<<1)|1
typedef long long ll;
using ull = unsigned long long;
const int mx = 2e5 + 10;
const int mod = 1e9 + 7;
int a[mx];
int main() {
int t;
scanf("%d", &t);
auto solve = [](int n) {
for (int i=1;i<=n;i++) {
for (int j=i+1;j<=n;j++) {
if (__gcd(a[i],a[j]) <= 2)
return "YES";
}
}
return "NO";
};
while (t--) {
int n;
scanf("%d", &n);
for (int i=1;i<=n;i++)
scanf("%d", a+i);
printf("%s\n", solve(n));
}
return 0;
}
B - Serval and Inversion Magic
解题思路:找到连续的一段,反转之后可以与之对称的相等,否则就不行。
#include<bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f3f
#define lson l,mid,rt<<1
#define rson mid+1,r,(rt<<1)|1
typedef long long ll;
using ull = unsigned long long;
const int mx = 2e5 + 10;
const int mod = 1e9 + 7;
char s[mx];
int main() {
int t;
scanf("%d", &t);
auto solve = [](int n) {
int be = -1, en = -1;
auto findpos = [n](int x) {
return 1 + n - x;
};
int mid = (1 + n) >> 1;
for (int i=1;i<=mid;i++) {
if (s[i] != s[findpos(i)]) {
be = i;
break;
}
}
if (be == -1) return "YES";
for (int i=mid; i; i--) {
if (s[i] != s[findpos(i)]) {
en = i;
break;
}
}
for (int i=be; i<=en; i++) {
if (s[i] == s[findpos(i)])
return "NO";
}
return "YES";
};
while (t--) {
int n;
scanf("%d", &n);
scanf("%s", s+1);
printf("%s\n", solve(n));
}
return 0;
}
解题思路:单算每个值的贡献,一个值要么在合并数组中出现2次,1次,或者0次。一次和两次的贡献都为1,所以枚举计算每个数的贡献相加即可。设某个值在m+1次数组中出现的次数是v,那么出现2次的次数就是v * (v - 1),出现一次的次数是v * (m + 1 - v)。
#include<bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f3f
#define lson l,mid,rt<<1
#define rson mid+1,r,(rt<<1)|1
typedef long long ll;
using ull = unsigned long long;
const int mx = 2e5 + 10;
const int mod = 1e9 + 7;
int a[mx];
map <int, int> mp;
int main() {
int t;
scanf("%d", &t);
auto solve = [](int n) {
};
while (t--) {
int n, m;
scanf("%d%d", &n, &m);
mp.clear();
for (int i=1;i<=n;i++) {
scanf("%d", a + i);
mp[a[i]] = m + 1;
}
for (int i=1;i<=m;i++) {
int q, v;
scanf("%d%d", &q, &v);
mp[a[q]] -= m + 1 - i;
mp[v] += m + 1 - i;
a[q] = v;
}
ll ans = 0;
for (auto ent: mp) {
int v = ent.second;
ans += 1ll * v * (v - 1) / 2;
ans += 1ll * v * (m + 1 - v);
}
printf("%lld\n", ans);
}
return 0;
}
D - Serval and Shift-Shift-Shift
解题思路:要想异或改变某个位置的值,那么肯定得找一位是1的位置异或。我们假设想改变i位置的值,但是同时不改变大于i位置或者不改变小于i位置的值,那么就得找一个位置j,j位置值为1,但是大于j位置的值都是0或者小于j位置的值都是0。那么当j左移或者右移到i位置时进行异或有一边的值是不会受影响的。根据这个道理,我们可以找到一个位置j,先把他的右边值都变成相等,然后再变换j的位置为最右边的那个j(因为满足条件的j有两种情况,先找其中一个再用另一个),用另一个j进行左边值的变换,这样就不会改变右边已经变换过的值,所以最终每个值都看一遍,不会超过n次。
#include<bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f3f
#define lson l,mid,rt<<1
#define rson mid+1,r,(rt<<1)|1
typedef long long ll;
using ull = unsigned long long;
const int mx = 2e3 + 10;
const int mod = 1e9 + 7;
char a[mx], b[mx], c[mx];
map <int, int> mp;
int main() {
int t;
scanf("%d", &t);
auto solve = [](int n) {
for (int i=1;i<=n;i++)
if (a[i] == '1')
return i;
return -1;
};
auto solve2 = [](int n) {
int i;
for (i = 1; i <= n; i++) {
if (a[i] == b[i] && a[i] == '0')
continue;
return i;
}
return i;
};
auto solve1 = [](int n, int k) {
for (int i=1; i<=n; i++)
c[i] = a[i];
if (k > 0) {
for (int i=1;i<=n-k;i++) {
a[i] = (a[i] - '0') ^ (a[i+k] - '0');
a[i] += '0';
}
//puts("#############");
//printf("%d %s\n", k, a + 1);
//puts("#############");
return ;
}
for (int i=-k+1; i<=n;i++) {
a[i] = (a[i] - '0') ^ (c[i+k] - '0');
a[i] += '0';
}
//puts("#############");
//printf("%d %s\n", k, a + 1);
//puts("#############");
};
while (t--) {
int n;
vector <int> vec;
scanf("%d", &n);
scanf("%s%s", a + 1, b + 1);
int pos = solve2(n);
if (pos == n + 1) {
puts("0");
continue;
}
if (a[pos] == '0') {
int tp = solve(n);
if (tp == -1) {
puts("-1");
continue;
}
solve1(n, tp - pos);
vec.push_back(tp - pos);
}
int last = -1;
for (int i=pos+1; i<=n;i++) {
if (a[i] == b[i]) {
if (a[i] == '1')
last = i;
continue;
}
if (a[i] == '0') last = i;
vec.push_back(pos - i);
solve1(n, pos - i);
}
if (a[pos] != b[pos]) {
if (last == -1) {
puts("-1");
continue;
}
solve1(n, last - pos);
vec.push_back(last - pos);
}
for (int i=pos-1; i; i--) {
if (a[i] != b[i]) {
solve1(n, last - i);
vec.push_back(last - i);
}
}
printf("%d\n", vec.size());
for (int v: vec) {
printf("%d ", v);
}
puts("");
}
return 0;
}