Codeforces Round #685 (Div. 2)
A. Subtract or Divide
题意
给你一个正整数 (n), 每次可以执行两种操作:
- (n = n-1)
- (n = n/x (n \% x == 0))
问 (n) 变成 (1), 最小要执行几次?
思路
- 偶数:直接变成 (2), 然后变成 (1),
- 奇数:先减 (1), 变成 (2), 然后变成 (1)
代码
#include <bits/stdc++.h>
#define lowbit(x) x & (-x)
#define mes(a, b) memset(a, b, sizeof a)
#define fi first
#define se second
#define pb push_back
#define pii pair<int, int>
typedef unsigned long long int ull;
typedef long long int ll;
const int maxn = 1e6 + 10;
const int maxm = 1e5 + 10;
const ll mod = 1e9 + 7;
const ll INF = 1e18 + 100;
const int inf = 0x3f3f3f3f;
const double pi = acos(-1.0);
const double eps = 1e-8;
using namespace std;
int main() {
int T, n;
scanf("%d", &T);
while(T--) {
scanf("%d", &n);
if(n <= 3) printf("%d
", n-1);
else if (n % 2) printf("%d
", 3);
else printf("2
");
}
return 0;
}
B. Non-Substring Subsequence
题意
给你一个长度为 (n) 的 (01) 字符串 (a), (q) 个询问,每次询问能否在字符串 (a) 中找到不连续的子序列 (b) 等于 (a[l_i...r_i])。
思路
枚举 (l, r) 被断开的位置,其他位置暴力查找即可。
代码
#include <bits/stdc++.h>
#define pb push_back
#define fi first
#define se second
#define mes(a, b) memset(a, b, sizeof a)
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
const int maxn = 1e3 + 100;
const int mx = 1e5;
const ull seed = 133331;
const ll inf = 1e15;
int T, n, m;
char a[maxn];
int main() {
scanf("%d", &T);
while(T--) {
scanf("%d%d%s", &n, &m, a+1);
int l, r;
while(m--) {
scanf("%d%d", &l, &r);
int flag = 0, w;
for(int i = l; i < r && !flag; i++) {
w = 1;
for(int j = l; j <= i; j++) {
while(w <= n && a[w] != a[j]) w++;
w++;
}
w++; //因为断开,所以这边要++
for(int j = i+1; j <= r; j++) {
while(w <= n && a[w] != a[j]) w++;
w++;
}
if(w <= n+1) flag = 1;
}
puts(flag ? "YES" :"NO");
}
}
return 0;
}
C. String Equality
题意
给你两个字符串 (a, b) ,可以对字符串 (a) 进行两种操作:
- 交换任意两个字符
- 把连续相同的 (k) 个字符 (c) 转变为 (c+1) (’(z)‘ 字符无法转变 )
问字符串 (a), 是否能在有限制操作内转变为字符串 (b)。
思路
因为可以任意交换位置,所以把字符串 (a), (b) ,进行排序,每次暴力转变即可。
代码
#include <bits/stdc++.h>
#define lowbit(x) x & (-x)
#define mes(a, b) memset(a, b, sizeof a)
#define fi first
#define se second
#define pb push_back
#define pii pair<int, int>
typedef unsigned long long int ull;
typedef long long int ll;
const int maxn = 1e6 + 10;
const int maxm = 1e5 + 10;
const ll mod = 1e9 + 7;
const ll INF = 1e18 + 100;
const int inf = 0x3f3f3f3f;
const double pi = acos(-1.0);
const double eps = 1e-8;
using namespace std;
int T, n, m;
char ch[maxn];
int a[30], b[30];
int main() {
scanf("%d", &T);
while(T--) {
mes(a, 0); mes(b, 0);
scanf("%d%d", &n, &m);
scanf("%s", ch+1);
for(int i = 1; i<= n; i++) a[ch[i]-'a']++;
scanf("%s", ch+1);
for(int i = 1; i <= n; i++) b[ch[i]-'a']++;
int flag = 1;
for(int i = 0; i < 26 && flag; i++) {
if(a[i] < b[i]) flag = 0;
if((a[i] - b[i]) % m) flag = 0;
a[i+1] += a[i] - b[i];
}
puts(flag?"Yes":"No");
}
return 0;
}
D. Circle Game
题意
起始点在 ((0, 0)) , 每次可以让 (x+k), 或者 (y + k) , 并且使得走之后位置 ((x_1, y_1)),满足 (x_1^2 + y_1^2 le d^2)。(Ashish) 为先手,谁不能走则输了,问谁能赢得这次游戏?
思路
找最大的(x), 满足 (x^2 + x^2 le d^2)
- ((x+k)^2 + x^2 le d), 则先手胜
- ((x+k)^2 + x^2 > d), 则先手败
((x+k)^2 + x^2 > d) 时,先手走 (x+k), 那么后手走 (y+k), 控制 (x = y) 即可。如果((x+k)^2 + x^2 le d),则先手走一步之后可以把状态转变为 ((x+k)^2 + x^2 > d) , 就必胜了。
代码
#include <bits/stdc++.h>
#define pb push_back
#define fi first
#define se second
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
const int maxn = 1e6 + 100;
const int mx = 1e5;
const ull seed = 133331;
const ll inf = 1e15;
ll T, n, m;
int main() {
scanf("%lld", &T);
while(T--) {
scanf("%lld%lld", &n, &m);
ll x = max(int(sqrt(n * n) / 2/ m)-2, 0);
x *= m;
while(x * x * 2 <= n * n) x += m;
x -= m;
if(x * x + (x+m) * (x+m) <= n*n || x*x*2 > n*n)
puts("Ashish");
else puts("Utkarsh");
}
return 0;
}
E1、E2. Bitwise Queries
题意
给你一个长度为 (n) ((4 le n le 2^{16}, n = 2^k)) 的数组 (a (a_i in [0, n-1])), 可以执行以下三种询问。
-
(AND i j) , 询问 (a_i & a_j)
-
(XOR i j) , 询问 (a_i oplus a_j)
-
(OR i j), 询问 (a_i | a_j)
在最多执行 (n+1) 次询问中,猜出原数组 (a) 的值。
思路
-
根据题目给的限制可以知道,要么数组存在两个相同的值,要么数组是一个 (0) ~ (n-1) 的排列。
-
首先执行 (XOR 1 i), (2 le i le n)。
-
判断是否出现 (a_1 oplus a_i = 0), 那么执行 (AND 1 i),因为 (a_1 = a_i), 就可以知道 (a_1) 的值
-
判断是否出现 (a_1 oplus a_i = 0, a_1 oplus a_j = 0) ,那么执行 (AND i j),因为 (a_i = a_j), 就可以知道 (a_i) 的值
-
否则找出 (a_1 oplus a_i = 1, a_1 oplus a_j = 2), 那么执行 (AND 1 i)、 (AND 1 j),所以 (a_1 = (a_1 &a_i) | (a_1&a_j))
代码
#include <bits/stdc++.h>
#define lowbit(x) x & (-x)
#define mes(a, b) memset(a, b, sizeof a)
#define fi first
#define se second
#define pb push_back
#define pii pair<int, int>
typedef unsigned long long int ull;
typedef long long int ll;
const int maxn = 1e6 + 10;
const int maxm = 1e5 + 10;
const ll mod = 1e9 + 7;
const ll INF = 1e18 + 100;
const int inf = 0x3f3f3f3f;
const double pi = acos(-1.0);
const double eps = 1e-8;
using namespace std;
int T, n, m;
int a[maxn], b[maxn], c[maxn];
int main() {
scanf("%d", &n);
for(int i = 2; i<= n; i++) {
printf("XOR %d %d
", 1, i);
fflush(stdout);
scanf("%d", &b[i]);
}
int flag = 0, x, y;
for(int i = 2; i <= n; i++) {
if(!b[i]) {
printf("AND 1 %d
", i);
fflush(stdout);
scanf("%d", &a[1]);
flag = 1;
break;
}
if(c[b[i]]) {
printf("AND %d %d
", c[b[i]], i);
fflush(stdout);
scanf("%d", &a[i]);
a[1] = a[i] ^ b[i];
flag = 1;
break;
}
c[b[i]] = i;
}
if(!flag) {
for(int i = 2; i <= n; i++) {
if(b[i] == 1) {
printf("AND 1 %d
", i);
fflush(stdout);
scanf("%d", &x);
}
if(b[i] == 2) {
printf("AND 1 %d
", i);
fflush(stdout);
scanf("%d", &y);
}
}
a[1] = x|y;
}
printf("! %d ", a[1]);
for(int i = 2; i<= n; i++) {
printf("%d ", a[1] ^ b[i]);
}
printf("
");
return 0;
}
F. Nullify The Matrix
题意
你有一个 (n*m) 的矩阵,(Ashish) 为先手,每轮可以执行以下操作,直到当前不能操作为止(既全0矩阵)
- 你可以选择一个起点 ((r_1, c_1)) , 选择一个终点 ((r_2, c_2)) ,满足 (r_1 le r_2, c_1 le c_2)
- 把 (a[r1][c1]) 减小至 ([0, a[r1][c1]-1])
- 选择任意一条起点到终点的最短路径,可以把除起点外的任意一点修改成任一非负数(每个单元格修改独立)
思路
-
可以把矩阵中 (r_x+c_x) 相同的为一组,当执行一次操作的时候,是对从 ([c_1+r_1, c_1+r_1+1, c_1+r_1+2, ..., c_2+r_2]) 中的每一组中选择一个元素进行修改,
-
(ord(d) = a[r_1][c_1]oplus a[r_2][c_2] oplus ... a[r_x][c_x] forall_{i=1}^x r_i +c_i = d) 。 那么存在两种状态
- (S_0 : forall ord(d) = 0)
- (S_1:in ord(d) eq 0)
-
最终态为 (S_0) 。
- 当在 (S_0) 状态上执行一步,一定会转变为 $ S_1$
- 当在 (S_1) 状态上执行一步,可以转变为 (S_0) , 只要把每组 (ord(d) eq 0) 中取出一个变为组内其他值的异或和既可。
-
当初始状态为 (S_0) 时,后手必赢。反之,后手必败。
代码
#include <bits/stdc++.h>
#define pb push_back
#define fi first
#define se second
#define mes(a, b) memset(a, b, sizeof a)
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
const int maxn = 1e3 + 100;
const int mx = 1e5;
const ull seed = 133331;
const ll inf = 1e15;
int n, m, T;
int a[maxn];
int main() {
scanf("%d", &T);
while(T--) {
mes(a, 0);
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; i++) {
for(int j = 1, x; j <= m; j++) {
scanf("%d", &x);
a[i+j] ^= x;
}
}
int flag = 0;
for(int i = 2; i <= m+n; i++) {
if(a[i]) flag = 1;
}
puts(flag ? "Ashish" : "Jeel");
}
return 0;
}