zoukankan      html  css  js  c++  java
  • AtCoder Grand Contest 043 部分题解

    警告,这里只有 (AB) 题解,努力一下也许能再做个一题

    这场打得好爽,rank (299),涨了 (141)

    AGC043A

    乍一看有点不知所措。BFS?暴力?

    让我们冷静分析一下。要达成目标,必须有至少一条从左上到右下的路径。

    感受一下:

    xxx..
    ..x..
    ..xx.
    ...x.
    ...xx
    

    注意到操作是同时对一个矩形区域操作。不难发现:这样可以对路径上任意一段连续序列取反。

    怎样操作最优呢?

    根据首尾,可以分为四种情况:

    #.#.# (答案:3)
    .#.#. (答案:2)
    #.#. (答案:2)
    .#.# (答案:2)
    

    综上,答案就是路径中连续的"#"的数量。

    (dp) 就可以了。

    我自己测的时候把“#”打成"X",懵逼了两分钟

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    #define mit map<int,int>::iterator
    #define sit set<int>::iterator
    #define itrm(g,x) for(mit g=x.begin();g!=x.end();g++)
    #define itrs(g,x) for(sit g=x.begin();g!=x.end();g++)
    #define ltype int
    #define rep(i,j,k) for(ltype(i)=(j);(i)<=(k);(i)++)
    #define rap(i,j,k) for(ltype(i)=(j);(i)<(k);(i)++)
    #define per(i,j,k) for(ltype(i)=(j);(i)>=(k);(i)--)
    #define pii pair<int,int>
    #define fi first
    #define se second
    #define mpr make_pair
    #define pb push_back
    #define fastio ios::sync_with_stdio(false)
    const int inf=0x3f3f3f3f,mod=1000000007;
    const double pi=3.1415926535897932,eps=1e-6;
    void chmax(int &x,int y){if(x < y) x = y;}
    void chmin(int &x,int y){if(x > y) x = y;}
    int n,m,dp[105][105];char s[105][105];
    int main()
    {
        scanf("%d%d",&n,&m);
        rep(i,1,n) scanf("%s",s[i]+1);
        dp[1][1] = (s[1][1] == '#');
        rep(i,1,n) rep(j,1,m)
        if(i != 1 || j != 1){
            dp[i][j] = inf;
            char cur = s[i][j];
            if(i > 1) {
                char prev = s[i-1][j];
                if(prev == cur) chmin(dp[i][j], dp[i-1][j]);
                else chmin(dp[i][j], dp[i-1][j] + (cur == '#'));
            }
            if(j > 1) {
                char prev = s[i][j-1];
                if(prev == cur) chmin(dp[i][j], dp[i][j-1]);
                else chmin(dp[i][j], dp[i][j-1] + (cur == '#'));
            }
        }
        printf("%d
    ",dp[n][m]);
        return 0;
    }
    

    AGC043B

    又是一道第一眼看没有思路的题。

    这道题让我想起了agc006d。其实这两题做法完全不同。

    我们不考虑 (O(n^2))

    首先我们发现,把原数列每个数减少 (1) 对答案没有任何影响。

    然后,先看只有 (0)(2) 的情况。这样答案要么是 (0) ,要么是 (2)

    我比赛时先考虑反推:最后的结果是 (2) ,原来可能的序列有:

       0 2
      2 2 0
     0 2 0 0
    2 2 0 0 0
    

    这个做法好像没什么前途。

    换个思路,正向思考,我们假设只有一个 (2) ,两边有足够的 (0) ,它会这样发展:

    0 0 0 0 0 0 2 0 0 0 0 0 0
     0 0 0 0 0 2 2 0 0 0 0 0
      0 0 0 0 2 0 2 0 0 0 0
       0 0 0 2 2 2 2 0 0 0
        0 0 2 0 0 0 2 0 0
         0 2 2 0 0 2 2 0
          2 0 2 0 2 0 2
           2 2 2 2 2 2
    

    是不是有点眼熟?它就和组合数模 (2) 的图案一样!

    有些图案在外面被忽略了,但是显示出来的一定不会受到影响。因为已经在外面的,怎样向左下或右下走,都不能走回去。

    所以算组合数模 (2) (也就是这个组合数的奇偶性)就行了!

    如果第一行有多个 (2) 呢?它们会互相叠加,偶数个叠加在一起会消除。所以,先得出对答案有影响的位置数 (num) ,如果 (num % 2)(0) ,答案为 (0),否则为 (2)

    只有 (0)(1) 的情况同理。只有 (1)(2) 的情况,把每个数减去 (1) ,也变成的左边的那种情况。

    如果 (0,1,2) 都有呢?

    答案不能超过 (1) ,因为序列中的 (1) 会持续造成影响,(|0-1| = |2-1| = 1),即 (1) 不会完全被消掉。在倒数第 (2) 轮的时候如果至少有一个数非零,其中一定有一个数是 (1)

    又由于 (|0-1| = |2-1| = 1)(0)(2) 这时是等价的,可以直接把 (2) 看成 (0)

    细节方面,如何算出 (C(a,b)) 的奇偶性?

    (fac(i)) 表示 (i!) 中约数 (2) 的个数。计算组合时把相除改成相减,若计算出的值为 (0) ,则 (C(a,b)) 为奇数。

    最后记得特判所有数字相等的情况。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    #define mit map<int,int>::iterator
    #define sit set<int>::iterator
    #define itrm(g,x) for(mit g=x.begin();g!=x.end();g++)
    #define itrs(g,x) for(sit g=x.begin();g!=x.end();g++)
    #define ltype int
    #define rep(i,j,k) for(ltype(i)=(j);(i)<=(k);(i)++)
    #define rap(i,j,k) for(ltype(i)=(j);(i)<(k);(i)++)
    #define per(i,j,k) for(ltype(i)=(j);(i)>=(k);(i)--)
    #define pii pair<int,int>
    #define fi first
    #define se second
    #define mpr make_pair
    #define pb push_back
    #define fastio ios::sync_with_stdio(false)
    const int inf=0x3f3f3f3f,mod=1000000007;
    const double pi=3.1415926535897932,eps=1e-6;
    void chmax(int &x,int y){if(x < y) x = y;}
    void chmin(int &x,int y){if(x > y) x = y;}
    int n,a[1000005],fac[1000005],ans,cnt[4],mup=1;char s[1000005];
    int C(int x,int y){
        return fac[x] - fac[y] - fac[x - y];
    }
    int main()
    {
        scanf("%d%s",&n,s+1);
        rep(i,1,n) a[i] = s[i] - 49, cnt[a[i]]++;
        rep(i,1,n){
            fac[i] = fac[i-1];
            int ii = i;
            while(ii % 2 == 0) {
                ii /= 2;
                fac[i]++;
            }
        }
        int pp = (cnt[0]>0) + (cnt[1]>0) + (cnt[2]>0);
        if(pp <= 1){puts("0");return 0;}
        if(cnt[0] && cnt[1] && cnt[2]){
            rep(i,1,n) if(a[i] == 2) a[i] = 0;
        }
        else if(cnt[0] && cnt[2]){
            mup = 2;
        }
        else if(cnt[1] && cnt[2]){
            rep(i,1,n) a[i]--;
        }
        rep(i,1,n) if(a[i]) {
            ans ^= (C(n - 1,i - 1) == 0);
        }
        printf("%d
    ",ans * mup);
        return 0;
    }
    
  • 相关阅读:
    JSON就是名值对 name/value pair
    AjaxXMLHttpRequest
    英语单词分类记
    委托和事件的理解
    用float设置主页的左右两边菜单
    OCS通讯路径
    测试用Word写Blog
    第一课 C#入门
    nginx虚拟目录设置 alias 和 root
    vsftp 出错,无法创建文件的解决方法
  • 原文地址:https://www.cnblogs.com/yz-beacon-cwk/p/12544128.html
Copyright © 2011-2022 走看看