zoukankan      html  css  js  c++  java
  • Codeforces Round #685 (Div. 2) A-F

    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) 。 那么存在两种状态

      1. (S_0 : forall ord(d) = 0)
      2. (S_1:in ord(d) eq 0)
    • 最终态为 (S_0)

      1. 当在 (S_0) 状态上执行一步,一定会转变为 $ S_1$
      2. 当在 (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;
    }
    
  • 相关阅读:
    csu 1965
    csu 1947 三分
    Codeforces 336C 0-1背包
    POJ 1743 后缀数组
    POJ 2774 后缀数组
    UVA 12333 大数,字典树
    POJ 2942 圆桌骑士
    POJ 1503 大整数
    POJ 2342 树的最大独立集
    POJ 3088 斯特林
  • 原文地址:https://www.cnblogs.com/zhuyou/p/14032294.html
Copyright © 2011-2022 走看看