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;
    }
    
  • 相关阅读:
    关于求 p_i != i and p_i != i+1 的方案数的思考过程
    poj 3041 Asteroids 二分图最小覆盖点
    poj 1325 Machine Schedule 最小顶点覆盖
    poj 1011 Sticks 减枝搜索
    poj 1469 COURSES 最大匹配
    zoj 1516 Uncle Tom's Inherited Land 最大独立边集合(最大匹配)
    Path Cover (路径覆盖)
    hdu 3530 SubSequence TwoPoint单调队列维护最值
    zoj 1654 Place the Rebots 最大独立集转换成二分图最大独立边(最大匹配)
    poj 1466 Girls and Boys 二分图最大独立子集
  • 原文地址:https://www.cnblogs.com/yz-beacon-cwk/p/12544128.html
Copyright © 2011-2022 走看看