zoukankan      html  css  js  c++  java
  • Codeforces #641 div2 A

    A. Orac and Factors

    (Description:)

      设 (f(n))(n) 的最小约数 ((f(n) > 1))。那么对于一次操作而言 (n = n + f(n)),求第 (k) 次操作后,(n) 为多少?

    (Solution:)

      对于 (n) 是偶数的情况下,(f(n) = 2),那么加上 (f(n))(n) 仍然是偶数,所以每次都 (+ 2)

      对于 (n) 是奇数的情况下,(f(n)) 也一定是奇数,那么加上 (f(n)) 后,(n) 就变成了偶数。

    (Code:)

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    
    int main(){
        int t; cin >> t;
        while(t --){
            ll n, k;
            cin >> n >> k;
            if(n & 1){
                int mark = 0;
                for(int i = 2; i * i <= n; i ++){
                    if(n % i == 0){
                        n += i;
                        mark = 1;
                        break;
                    }
                }
                if(!mark) n += n;
                cout << n + (k - 1) * 2 << endl;
            }else{
                cout << n + k * 2 << endl;
            }
        }
        return 0;
    }
    


    B. Orac and Models

    (Description:)

      给定一个长为 (n) 的数组 (a),在数组挑选几个数组成一个新序列,要求新序列的任意两个数要满足:(j mod i = 0 and a_i < a_j)(i, j) 是该数在原数组的下标。

    (Solution:)

      设 (f[i]) 为以 (a_i) 结尾的构成合法新序列的最长长度。那么我们去枚举 (i) 的约数 (j),于是得到:(f[i] = max(f[i], f[j] + 1))

    (Code:)

    #include <bits/stdc++.h>
    using namespace std;
    const int N = 1e5 + 10;
    
    int n;
    int s[N], f[N];
    
    int main(){
        int t; cin >> t;
        while(t --){
            cin >> n;
            for(int i = 1; i <= n; i ++)
                scanf("%d", &s[i]);
            for(int i = 1; i <= n; i ++){
                f[i] = 1;
                for(int j = 1; j * j <= i; j ++){
                    if(i % j == 0){
                        if(s[i] > s[j])
                            f[i] = max(f[i], f[j] + 1);
                        if(s[i] > s[i / j])
                            f[i] = max(f[i], f[i / j] + 1);
                    }
                }
            }
            cout << *max_element(f + 1, f + n + 1) << endl;
        }
        return 0;
    }
    
    
    


    C. Orac and LCM

    (Description:)

      给定长度为 (n) 的数组 (a),求由 ((lcm(a_i, a_j) | i < j)) 得到一些数的 (gcd)

    (Solution:)

      单独看 (a_1),我们可以得到 (lcm(a_1,a_2),lcm(a_1,a_3),...,lcm(a_1,a_n))。则:

    [gcd(lcm(a_1,a_2), lcm(a_1,a_3), ..., lcm(a_1,a_n)) = lcm(a_1, gcd(a_2, a_3,..., a_n)) ]

      我们预处理出一个 (gcd) 的后缀,就可以简单的得出结果。

      证明一下上面的公式:

        假设:(lcm(a_1, a_2) = a_1 imes a_2 imes x_2),那么 (x_2 = frac{1}{gcd(a_1,a_2)});

        同理:(lcm(a_1,a_3) = a_1 imes a_3 imes x_3);那么 (x_3 = frac{1}{gcd(a_1,a_3)});

        那么设: (t = gcd(lcm(a_1,a_2),lcm(a_1,a_3)) = gcd(a_1 imes a_2 imes x_2, a_1 imes a_3 imes x_3) = a_1 imes gcd(a_2 imes x_2, a_3 imes x_3))

        因为:(gcd(ab, m) = gcd(a, m) imes gcd(b, m));

        所以:(t = a_1 imes gcd(a_2, a_3) imes gcd(x_2, x_3) imes gcd(a_2,x_3) imes gcd(a_3, x_2));

        由于:(gcd(frac{1}{a}, frac{1}{b}) = frac{1}{gcd(a,b)})

        则:(gcd(a_2, x_3) = gcd(frac{a_2}{1}, frac{1}{gcd(a_1,a_3)}) = frac{gcd(a_2,1)}{gcd(1,gcd(a_1,a_3))} = 1);

        同理:(gcd(a_3,x_2) = 1);

        那么:

         (t = a_1 imes gcd(a_2,a_3) imes gcd(x_2, x_3) = frac{a_1 imes gcd(a_2, a_3)}{gcd(gcd(a_1,a_2), gcd(a_1,a_3))});

      由:(gcd) 满足交换律:(gcd(gcd(a,b), gcd(a,c)) = gcd(a, a, b, c) = gcd(a, b, c) = gcd(a, gcd(b, c)));

        那么:(t = frac{a_1 imes gcd(a_2,a_3)}{gcd(a_1,gcd(a_2,a_3))} = lcm(a_1,gcd(a_2,a_3))).

      证毕。

    (Code:)

    #include <bits/stdc++.h>
    using namespace std;
    const int N = 1e5 + 10;
    typedef long long ll;
    
    int n;
    ll a[N], g[N];
    
    ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }
    
    ll lcm(ll a, ll b) { return a * b / gcd(a, b); }
    
    int main(){
        cin >> n;
        for(int i = 1; i <= n; i ++) 
            scanf("%d", &a[i]);
        g[n + 1] = 0;
        for(int i = n; i >= 1; i --)
            g[i] = gcd(g[i + 1], a[i]);
        ll ans = 0;
        for(int i = 1; i < n; i ++){
            ll tmp = lcm(a[i], g[i + 1]);
            ans = gcd(ans, tmp);
        }
        cout << ans << endl;
        return 0;
    }
    


    D. Orac and Medians

    (Description:)

      给定长为 (n) 的数组 (a) 和一个 (k),,问是否可以通过任意次操作将数组每个元素变为 (k)?

      操作是:将数组区间 ([l, r]) 的数变为该区间的中位数。

    (Solution:)

      很显然的一个判断是确认数组中有没有 (k) 这个元素。

      对于中位数的确认,显然涉及到了排序,但是时间不允许。但是如果我们只考虑长度 (2) 的区间,显然小的那个数就是中位数。那么对于固定的 (k) 来说,我们只需要他的左边或右边存在一个 (geq k) 的数,那么就可以变为 (k),那么此时我们就得到了两个连续的 (k),那么我们在这个区间上去扩展一个元素,即区间长度为 (3),无论第三个元素的大小,中位数都一定是 (k),那么我们就得到了三个连续的 (k),以此类推下去我们就可以构造出来了。

      那么我们接下来的任务就是在 (k) 的左边或右边搞出一个 (geq k) 的数,那么我们根据上面的思路,如果存在两个连续的数 (geq k),那么我们就可以扩展到三个数,四个数......直到遇到扩展的元素为 (k)

      那么我们就得到了一个条件:存在两个连续的数 (geq k)

      如果不满足上述条件是不是就一定不可以了呢?对于这种情况:(a_i, a_{i+1}, a_{i+2},(a_i geq k, a_{i+1} < k, a_{i+2} geq k)),显然也是可以的。所以只要满足这两个条件就可以了。

      还有一个坑点就是要特判 (n = 1) 的情况。

    (Code:)

    #include <bits/stdc++.h>
    using namespace std;
    const int N = 1e5 + 10;
    
    int n, k;
    int a[N];
    
    bool judge(){
        int mark = 0;
        for(int i = 1; i <= n; i ++){
            if(a[i] == k) mark = 1;
        }
        if(!mark) return 0;
        if(n == 1 && a[n] == k) return 1;
        for(int i = 2; i <= n; i ++){
            if(a[i] >= k && a[i - 1] >= k) return 1;
            if(i >= 3 && a[i] >= k && a[i - 2] >= k) return 1;
        }
        return 0;
    }
    
    
    int main(){
        int t; cin >> t;
        while(t --){
            cin >> n >> k;
            for(int i = 1; i <= n; i ++)
                scanf("%d", &a[i]);
            if(judge()) puts("yes");
            else puts("no");
        }
        return 0;
    }
    


    E. Orac and Game of Life

    (Description:)

      给出一个 (0, 1) 矩阵,每经过一轮循环矩阵就有可能变换。

      (1.) 如果一个元素存在一个相邻元素和他相同,那么该元素就会变换。

      (2.) 如果不存在,那么该轮循环就不会发生变换。

    (Solution:)

      显然的一个事实是:如果矩阵中不存在一组相邻的元素相同,那么矩阵就永远不会变。否则,矩阵的每一位元素都有可能发生变换,可以参考样例三。

      那么我们只需要把那些可以发生变换的元素提取出来,然后用他们去同化那些原本不会变的元素即可,记录下每个元素的第一次变换的循环是那一次即可。

    (Code:)

    #include <bits/stdc++.h>
    using namespace std;
    const int N = 1e3 + 10, INF = 0x3f3f3f3f;
    typedef pair<int, int> PII;
    typedef long long ll;
    
    int n, m, t;
    char s[N][N];
    int a[N][N];
    int vis[N][N];
    int d[N][N];
    
    int to[4][2] = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};
    
    int check(int x, int y){
        if(x >= 1 && x <= n && y >= 1 && y <= m) return 1;
        return 0;
    }
    
    int main(){
        cin >> n >> m >> t;
        for(int i = 1; i <= n; i ++)
            scanf("%s", s[i] + 1);
        memset(vis, 0, sizeof vis); 
        memset(d, INF, sizeof d); // 第一次变换的循环
    
        queue<PII> q;
        for(int i = 1; i <= n; i++)
            for(int j = 1; j <= m; j ++){
                a[i][j] = s[i][j] - '0';
                for(int k = 0; k < 4; k ++){
                    int x = i + to[k][0];
                    int y = j + to[k][1];
                    if(check(x, y) && s[x][y] == s[i][j]){
                        q.push({i, j}); // 提取存在相邻相同元素的
                        d[i][j] = 0; // 置为 0,因为原本就会变
                        vis[i][j] = 1; // 标记已经访问过
                        break;
                    }
                }
            }
        
        while(!q.empty()){
            PII t = q.front(); q.pop();
            int x = t.first, y = t.second;
            for(int i = 0; i < 4; i ++){ // 用这个元素去同化他周围的
                int xx = x + to[i][0];
                int yy = y + to[i][1];
                if(check(xx, yy) && !vis[xx][yy]){
                    q.push({xx, yy});
                    d[xx][yy] = d[x][y] + 1; 
                    vis[xx][yy] = 1; // 标记一下
                }
            }
        }
    
        while(t --){
            int x, y;
            ll p; // p 很大
            scanf("%d%d%lld", &x, &y, &p);
            p -= d[x][y]; // 减去需要同化的循环次数
            if(p <= 0 || d[x][y] == INF) printf("%d
    ", a[x][y]);
            else printf("%d
    ", a[x][y] ^ (p & 1));
        }
    
        return 0;
    }
    
  • 相关阅读:
    马尔科夫模型
    统计自然语言处理(第2版)目录
    linux运维学习笔记随想
    Redis 入门:(1)Linux下使用
    TextRank算法原理及应用示例
    实验十 团队作业6:团队项目用户验收&Beta冲刺
    关于tensorflow
    实验九 团队作业6:团队项目编码&Alpha冲刺
    实验八 团队作业4—团队项目需求建模与系统设计
    实验七 团队作业3:团队项目需求分析与原型设计
  • 原文地址:https://www.cnblogs.com/nonameless/p/12884751.html
Copyright © 2011-2022 走看看