A. Array Divisibility
对于当前ai,令其值为i的倍数即可
直接令ai=i,输出
code
void solve() {
int n;
cin >> n;
for (int i = 1; i <= n; i++)
cout << i << ' ';
cout << '\n';
}
B. Corner Twist
发现每一次操作对于对角元素所在的行、列的和都执行了(sum+1+2)%3
等价于操作前后 分别模3的值不变
遍历每一行,每一列
若对于任意i,j,(1<=i<=n,i<=j<=m),a数组中的sumi%3==b数组中的sumi%3,a数组中的sumj%3==b数组中的sumj%3,则必然可通过若干次操作使得a数组与b数组相同
code
void solve() {
int n, m;
cin >> n >> m;
vector<int> a(n + 1, 0), b(m + 1, 0);
for (int i = 1; i <= n; i++) {
getchar();
for (int j = 1; j <= m; j++) {
char x;
cin >> x;
a[i] += x-'0';
b[j] += x-'0';
}
}
for (int i = 1; i <= n; i++) {
getchar();
for (int j = 1; j <= m; j++) {
char x;
cin >> x;
a[i] -= x - '0';
b[j] -= x - '0';
}
}
int f = 1;
for (int i = 1; i <= n; i++) {
if (a[i] % 3 != 0) {
f = 0;
break;
}
}
for (int i = 1; i <= m; i++) {
if (b[i] % 3 != 0) {
f = 0;
break;
}
}
if (f)
cout << "YES\n";
else
cout << "NO\n";
}
C. Have Your Cake and Eat It Too
因为数据范围不大,直接暴力遍历所有的位置情况 [a,b,c],[a,c,b],[b,a,c],[b,c,a],[c,a,b],[c,b,a]
以[a,b,c]为例
从1开始遍历a数组,记la=1,当 记ra=i
从ra+1开始遍历b数组,记lb=ra+1,当 记rb=i
从rb+1开始遍历b数组,记lc=rb+1,当 时,符合题意,记rb=n,输出答案
code
int n;
int la, lb, lc, ra, rb, rc;
int p;
bool find(vector<int> a, vector<int> b, vector<int> c) {
la = 1;
int now = 0;
int f1 = 0;
for (int j = 1; j <= n; j++) {
now += a[j];
if (now >= p) {
f1 = 1;
ra = j;
break;
}
}
if (f1) {
lb = ra + 1;
f1 = 0;
now = 0;
for (int j = lb; j <= n; j++) {
now += b[j];
if (now >= p) {
f1 = 1;
rb = j;
break;
}
}
if (f1) {
lc = rb + 1;
f1 = 0;
now = 0;
for (int j = lc; j <= n; j++)
now += c[j];
if (now >= p) {
rc = n;
return true;
}
}
}
return false;
}
void solve() {
cin >> n;
int sum = 0;
vector<int> a(n + 1, 0), b(n + 1, 0), c(n + 1, 0);
for (int i = 1; i <= n; i++) {
int x;
cin >> x;
a[i] = x;
sum += x;
}
for (int i = 1; i <= n; i++) {
int x;
cin >> x;
b[i] = x;
}
for (int i = 1; i <= n; i++) {
int x;
cin >> x;
c[i] = x;
}
int f = 1;
p = sum / 3;
if (sum % 3)
p++;
for (int i = 1; i <= 6; i++) {
if (i == 1) {
bool isfind=find(a, b, c);
if (isfind == true) {
cout << la << ' ' << ra << ' ' << lb << ' ' << rb << ' ' << lc << ' ' << rc << '\n';
return;
}
}
if (i == 2) {
bool isfind = find(a, c, b);
if (isfind == true) {
cout << la << ' ' << ra << ' ' << lc << ' ' << rc << ' ' << lb << ' ' << rb << '\n';
return;
}
}
if (i == 3) {
bool isfind = find(b, a, c);
if (isfind == true) {
cout << lb << ' ' << rb << ' ' << la << ' ' << ra << ' ' << lc << ' ' << rc << '\n';
return;
}
}
if (i == 4) {
bool isfind = find(b, c, a);
if (isfind == true) {
cout << lc << ' ' << rc << ' ' << la << ' ' << ra << ' ' << lb << ' ' << rb << '\n';
return;
}
}
if (i == 5) {
bool isfind = find(c, a, b);
if (isfind == true) {
cout << lb << ' ' << rb << ' ' << lc << ' ' << rc << ' ' << la << ' ' << ra << '\n';
return;
}
}
if (i == 6) {
bool isfind = find(c, b, a);
if (isfind == true) {
cout << lc << ' ' << rc << ' ' << lb << ' ' << rb << ' ' << la << ' ' << ra << '\n';
return;
}
}
}
cout << "-1\n";
}
D. Swap Dilemma
若a,b数组中元素不相同,直接输出“NO”
考虑r-l=1,即相邻两个数组元素交换的情况
交换次数即为数组中元素逆序对的个数,套个板子(注意数组初始化范围的问题,不然会t……)
当a,b数组中逆序对差为偶数时,必然可通过任意次操作使得两个数组相同
code
struct Tr {
ll num;
ll j;
};
ll n;
Tr tra[N];
Tr trb[N];
ll inp[N];
ll lowbit(ll x) {
return x & -x;
}
bool mycmp(Tr x, Tr y) {
return x.j > y.j || (x.j == y.j && x.num > y.num);
}
ll fid(ll x) {
ll t = 0;
while (x) {
if(x<=n)
t += inp[x];
x -= lowbit(x);
}
return t;
}
void add(ll x) {
while (x <= n) {
inp[x]++;
x += lowbit(x);
}
}
void solve() {
unordered_map<int, int>mp;
cin >> n;
for (int i = 0; i <= n; i++)
inp[i] = 0;
for (int i = 1; i <= n; i++) {
int x;
cin >> x;
tra[i].num = i;
tra[i].j = x;
mp[x]++;
}
int f = 1;
for (int i = 1; i <= n; i++) {
int x;
cin >> x;
trb[i].num = i;
trb[i].j = x;
if (mp[x] > 0)
mp[x]--;
else
f = 0;
}
if (f == 0)
cout << "NO\n";
else {
int ansa = 0, ansb = 0;
sort(tra + 1, tra + n + 1, mycmp);
sort(trb + 1, trb + n + 1, mycmp);
for (int i = 1; i <= n; i++) {
ll k = tra[i].num;
ansa += fid(k);
add(k);
}
for (int i = 0; i <= n; i++)
inp[i] = 0;
for (int i = 1; i <= n; i++) {
ll k = trb[i].num;
ansb += fid(k);
add(k);
}
if (abs(ansa - ansb) % 2 == 0)
cout << "YES\n";
else
cout << "NO\n";
}
}