zoukankan      html  css  js  c++  java
  • ACM International Collegiate Programming Contest, Damascus University Collegiate Programming Contest(2018) 题解

    签到题


    A

    4min 1Y

    C

    45min 3Y

    题意

    给两个串,要把第一个串变成第二个串。每次选择一个半径r,然后以第一个串的中心为中心,r为半径,左右翻转。问最少几次操作?

    题解

    细节有点多。

    • 先是输出-1的情况。这个很好考虑
    • 然后遍历s1串,对于位置i,如果需要翻转(s1[i]=s2[n+1-i]),则打上标记1,不需要翻转(s1[i]=s2[i]).则打上标记0,如果翻不翻转都可以(s1[i]=s1[n+1-i]),打上标记2。
    • 遍历[1,n/2],对于打上标记2的位置,我们要决定是翻还是不翻,根据贪心,我们可以怠惰一点!对于打上标记2的位置,和前一个位置保持一致即可。

    F

    25min 1Y

    题解

    统计一下每个数字出现了多少次,出现了x次,对答案的贡献则为x!,相乘即为答案。

    J

    42min 2Y

    题解

    按题意模拟。

    冷静分析一下开局

    • 开场看了C觉得很基本,然后过了A,开始写C。
    • C细节没考虑清楚,用了10min,WA on test 2!
    #include <iostream>
    #include <cstring>
    using namespace std;
    typedef long long LL;
    const int N = 100000 + 10;
    int T;
    char s1[N], s2[N], s3[N];
    bool ok[N];
    int main() {
        scanf("%d", &T);
        while (T --) {
            scanf("%s %s", s1+1, s2+1);
    
            int n = strlen(s1+1);
            int mid = (n+1)/2;
            if (s1[mid] != s2[mid]) {
                printf("-1
    "); continue;
            }
            bool gg = 0;
            for (int i=1;i<mid;i++) {
                if (s1[i]==s2[i] && s1[n-i+1]==s2[n-i+1])
                    ok[i] = 1;
                else if (s1[i]==s2[n-i+1] && s1[n-i+1]==s2[i])
                    ok[i] = 0;
                else 
                    gg = 1;
            }
            if (gg) {
                printf("-1
    "); continue;
            }
    
            int ans = 0;
            ok[0] = 1;
            for(int i=1;i<mid;i++) {
                if (ok[i] != ok[i-1])
                    ans ++;
            }
            printf("%d
    ", ans);
        }
    }
    

    完全没有考虑s1[i]=s1[n+1-i]的情况。

    用了6分钟fix了一下。s1[i]=s1[n+1-i]

    int ans = 0;
    ok[0] = 1;
    for(int i=1;i<mid;i++) {
        if (ok[i] != ok[i-1] && ok[i] != 2)
            ans ++;
    }
    printf("%d
    ", ans);
    

    然后喵了个呜,又一次WA2

    • 我逃跑,用了5min时间过了F
    • 用了10min的时间J题WA2
    • 用了5min的时间fix了一下,人调换方向那个地方写得意识有点模糊。
    • 用了2min时间fix了一下C,很沙比的错误,比如说n = 7,前3位,标记为0 2 0的情况就智障掉了。

    前期比较容易细节没考虑清楚就上去写代码。C,J这两个模拟题都是这个原因吧。开始写代码之间,大概是抱着“随便搞搞就好”的想法。这种态度很沙比的啊。

    • 我在求什么?
    • 在模拟的过程,变量会如何变化?

    这两个问题都考虑得不清楚吧!

    中档题


    B

    Hash的做法很容易看出。然后就unlimited WA TLE MLE

    搞Hash的经验严重不足?

    边的种数不会超过n种,因此我们放n个桶。每个桶记录这种边出现的次数。

    然后就是对一个XXX进制下,n位数的hash了【双hash保平安】

    #include <iostream>
    #include <algorithm>
    #include <vector>
    #include <unordered_map>
    
    using namespace std;
    typedef long long LL;
    
    const int N = 10000008;
    const LL MOD1 = 100000007;
    const LL MOD2 = 923439347;
    
    int T;
    int n, x, y;
    int val[N]; vector<int> v;
    LL k1[N], k2[N];
    
    unordered_map< LL, int > mp;
    
    int main() {
        scanf("%d", &T);
        
        k1[0] = k2[0] = 1;
        for(int i=1;i<N;i++) {
            k1[i]=k1[i-1]*10007LL%MOD1;
            k2[i]=k2[i-1]*20007LL%MOD2;
        }
        while (T --) {
            scanf("%d", &n);
            v.clear();
            for (int i = 1; i <= n; i ++) {
                scanf("%d %d", &x, &y);
                if (x > y) swap(x, y);
                val[i] = (2*n+1)*x + y;
                v.push_back(val[i]);
            }
            sort(v.begin(), v.end());
            v.erase(unique(v.begin(), v.end()), v.end());
            for(int i=1;i<=n;i++) {
                val[i] = lower_bound(v.begin(), v.end(), val[i])-v.begin()+1;
            }
            mp.clear();
            LL sum1, sum2;
            LL ans=0;
            for (int i=1;i<=n;i++) {
                sum1 = 0, sum2 = 0;
                for(int j=1;j<=n;j++) {
                    sum1 += k1[val[j]]; 
                    sum1 %= MOD1;
                    sum2 += k2[val[j]];
                    sum2 %= MOD2;
                }
                mp[sum1*MOD2 + sum2] ++;
                for(int j=i+1;j<=n;j++) {
                    sum1 += k1[val[j]]-k1[val[j-i]]; 
                    sum1 = (sum1%MOD1+MOD1)%MOD1;
                    sum2 += k2[val[j]]-k2[val[j-i]];
                    sum2 = (sum2%MOD2+MOD2)%MOD2;
                    mp[sum1*MOD2+sum2] ++;
                }
                for (auto x: mp) {
                    LL v = x.second;
                    ans += v * (v - 1) / 2;
                }
                mp.clear();
            }
    
    
            printf("%lld
    ", ans);
        }
    }
    

    G

    题意

    修改最少的元素,使得序列的GCD为x,LCM为y。

    题解

    先判-1(一番激烈的讨论)

    如果a[i]%x!=0 or y%a[i]!=0,那么i就是个卜。

    直觉告诉我们把一个数字变成x,另一个数字变成y,只要其它的数字不卜,生活就有保障了。

    • 如果卜的个数>=2,那么答案就是卜的个数了。
    • 否则答案可能是1,可能是2,可能是0
    • 答案是0,很简单。
    • 答案是1,很不简单。我们枚举一下每个数字,看他是否能力挽狂澜,我们把枚举的数字放逐掉,求出其它数字的GCD&LCM(先预处理前缀后缀GCD&LCM),然后看一看世界末日前怎么办?来得及拯救吗?【具体怎么做,留给读者思考。】
    • 答案是2,很简单,加个else

    I

    题意

    n堆石头,两种操作,两人轮流操作。

    • 可以从一堆石头中拿走一个石头。
    • 如果每堆石子都至少有1个,可以从每堆石头中拿走一个石头。

    先手胜?后手胜?

    题解

    冷静分析一下

    • n%2=1. 易证,留给读者思考【读者似乎就我一个人。】
    • n%2=0. 这个得冷静分析一下。
    • min=1, 先手可以把后手气死。类似于chomp Game的模型。
    • min=2, 第一种操作肯定不可以施展的!不然会被气死。既然只能施展第二种操作,胜负显而易见了吧。
    • min=3, 先手可以把后手气死。类似于chomp Game的模型。
    • min=4, .......

    博弈在模型的直觉很重要的吖!这题意识到了chomp Game就很简单了吧。

    K

    题意

    n个点,n条边,多组查询,求两点间最短路。

    题解

    先去掉一条边edge,那么这个图就是一颗树了。

    枚举,u到v是否要经过edge即可。

    冷静分析一下中期

    • 先用了10min施展G,施展了一大半,然后咕咕咕了。
    • 先用了10min施展B题。没考虑清楚自己在hash什么东西,耽误了一段时间,然后WA11
    • 用了13min过了K。
    • 用了3min过了G的样例,WA2
    • 开始unlimited Fix G,中间用了很长一段时间次饭去了。但调G的时间至少有1小时。
      • Bug1:没读完就输出结果,WA
      • Bug2:复杂度nsqrt(n).【不错,有创意】
      • Bug3:n=1的特判不到位,搞得后面越界了。一大波RE。
    • 用了一个小时Fix B题的Hash,好不容易开始双hash然后MLE。枚举长度后清空,解决了问题。
    • 用了半个小时搞I

    emmmm....大部分时间都在Fix辣鸡。。。

    考虑清楚再写啊······

    羊肉粉丝汤弱鸡啊。

    感觉30min 4题,2h30min8题是比较合理的。


  • 相关阅读:
    元类
    redis--py链接redis【转】
    redis--py操作redis【转】
    python format 用法详解
    初识多线程__下
    mysql学习笔记五 —— MHA
    mysql学习笔记四 —— AB复制
    mysql学习笔记三 —— 数据恢复与备份
    mysql学习笔记二 —— 权限体系
    mysql学习笔记一 —— 数据的增删改查
  • 原文地址:https://www.cnblogs.com/RUSH-D-CAT/p/9119887.html
Copyright © 2011-2022 走看看