• CF#581 (div2)题解


    CF#581 题解

    A BowWow and the Timetable

    如果不是4幂次方直接看位数除以二向上取整,否则再减一

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<algorithm>
    #include<vector>
    #include<set>
    #include<map>
    using namespace std;
    #define MAXN 200006
    int n , m , A[MAXN];
    char ch[MAXN];
    int main() {
        scanf("%s",ch);
        int len = strlen( ch );
        int flg = 0;
        for( int i = 1 ; i < len ; ++ i ) if( ch[i] != '0' ) { flg = 1; break; }
        if( ! flg ) cout << len / 2;
        else cout << ( len + 1 ) / 2;
    }
    
    

    B Mislove Has Lost an Array

    贪心做

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<algorithm>
    #include<vector>
    #include<set>
    #include<map>
    using namespace std;
    #define MAXN 200006
    int n , l , r;
    int main() {
        cin >> n >> l >> r;
        int mn , mx; mn = mx = 0;
        for( int i = l - 1 ; i >= 0 ; -- i ) mn += ( 1 << i );
        mn += ( n - l );
        for( int i = r - 1 ; i >= 0 ; -- i ) mx += ( 1 << i );
        mx += ( n - r ) * ( 1 << r - 1 );
        cout << mn << ' ' << mx << endl;
    }
    

    Anna, Svyatoslav and Maps

    直接在给定path上跑,贪心一下,如果当前点到下个点距离不到在path中的距离,加入这个点然后把当前点设置成这个点

    最后一个点必须加入(

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <cmath>
    #include <algorithm>
    #define mem( a ) memset( a , 0x3f , sizeof a )
    #define MAXN 1000016
    using namespace std;
    int ans[MAXN] , pre[MAXN] , G[106][106];
    int n , m , dat[MAXN];
    char str[3000];
    void print(int ps) {
        if (!ps) return;
        print(pre[ps]);
        printf("%d ", dat[ps]);
    }
    int main() {
        mem( ans ); mem( G );
        scanf("%d", &n);
        for (int i = 1; i <= n; ++i) {
            scanf("%s", str + 1);
            for (int j = 1; j <= n; ++j)if (str[j] == '1')
                G[i][j] = 1;
        }
        for (int k = 1; k <= n; ++k)
            for (int i = 1; i <= n; ++i)
                for (int j = 1; j <= n; ++j) if (i != j)
                    G[i][j] = min(G[i][j], G[i][k] + G[k][j]);
        ans[1] = 0;
        scanf("%d", &m);
        for (int i = 1; i <= m; ++i) scanf("%d", &dat[i]);
        for (int i = 2; i <= m; ++i)
            for (int j = 1; j <= n; ++j)
                if ( i - G[j][dat[i]] > 0 && dat[i - G[j][dat[i]]] == j && ans[i - G[j][dat[i]]] + 1 < ans[i] ) {
                    ans[i] = ans[i - G[j][dat[i]]] + 1;
                    pre[i] = i - G[j][dat[i]];
                }
        printf("%d
    ", ans[m] + 1);
        print(m);
    }
    

    D1 & D2 Kirk and a Binary String

    首先,最优解一定是把原来的某些1变成0

    假设在某种情况下,可以把0变成1

    • 如果它左右有一个位置是0,那么肯定不能变成1,否则答案+1
    • 如果左右都是1,那么也不能变成1,不然总长度+1

    定义一个序列是fixed的,满足一下条件:

    • 10是fixed的。

    • p是fixed,那么1p0是fixed的。

    • p、q是fixed,那么pq是fixed

    很容易发现,fixed的子段有几个性质,首先1和0的个数一样,每个段中最长不降一定是长度的一半(可以通过全部选0或者选1做到)并且fixed的子段一定不能1变0(任意变最长不降数量一定增加)

    那么可以把一个fixed的子段看做一个可变的数,它既可以是0也可以是1,这种子段直接删掉就好了。不断重复删除直到序列中没有剩下的fixed的子段,也就一定形成了0...01…1的形式,这个时候这些1一定都是可以删除的。其实最后形成的序列是非fixed的序列组成的一个不降序列,在这个的基础上把fixed的序列添加进去,并且fixed的序列跟着这个序列取就行了,如果我们把这个序列全部变0,显然fixed的序列就全部选0就好了。

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<algorithm>
    #include<stack>
    using namespace std;
    #define MAXN 100006
    char ch[MAXN];
    int n , book[MAXN];
    stack<pair<char,int> > S;
    int main() {
        scanf("%s",ch);
        n = strlen( ch );
        for( int i = 0 ; i < n ; ++ i )
            if( ch[i] == '0' && !S.empty() && S.top().first == '1' ) S.pop();
            else S.push( make_pair( ch[i] , i ) );
        while( !S.empty() ) {
            if( S.top().first == '1' ) book[S.top().second] = 1;
            S.pop();
        }
        for( int i = 0 ; i < n ; ++ i )
            putchar( book[i] ? '0' : ch[i] );
    }
    
    

    Natasha, Sasha and the Prefix Sums

    可以假设k[x][y]表示x个1y个-1使得最大前缀和小于等于0的情况总数。考虑dp转移,当x > y的时候,显然k的值是0,否则,我们一定可以在最后放一个-1或者1使得这个序列最大前缀和仍然小于等于0。所以有(k[x][y]=k[x-1][y]+k[x][y-1])

    然后设dp数组,dp[x][y]是x个1y个-1的答案。

    对于这个dp我们考虑从前面添加数的两种转移:

    • 添加一个1,显然对于所有方案答案都要增加1,那么增加的总数就是总排列数,也就是一个组合数(left(egin{array}{c}{x+y-1} \ {y}end{array} ight))(相当于是一个插板法)
    • 添加一个-1,对于方案不是完全小于等于0的的所有方案都要给答案-1。具体来说,减少了(left(egin{array}{c}{x+y-1} \ {x}end{array} ight)-k[x][y-1])

    大概就这样了,有不清楚的看官方题解吧(

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<algorithm>
    #include<stack>
    using namespace std;
    #define int long long
    #define MAXN 2006
    #define P 998244853
    int k[MAXN][MAXN] , dp[MAXN][MAXN];
    int J[MAXN * 10] , inv[MAXN * 10] , invJ[MAXN * 10];
    int n , m;
    int C( int x , int y ) {
        return J[x] * invJ[y] % P * invJ[x - y] % P;
    }
    signed main() {
        cin >> n >> m;
        inv[0] = inv[1] = J[0] = invJ[0] = J[1] = invJ[1] = 1;
        for( int i = 2; i < 10 * MAXN ; ++ i ) J[i] = J[i - 1] * i , J[i] %= P , inv[i] = ( P - P/i )*inv[P%i] % P , invJ[i] = inv[i] * invJ[i - 1] % P;
        for( int i = 0 ; i <= m ; ++ i ) k[0][i] = 1;
        for( int i = 1 ; i <= n ; ++ i )
            for( int j = 1 ; j <= m ; ++ j ) if( i <= j )
                k[i][j] = k[i - 1][j] + k[i][j - 1] , k[i][j] %= P;
        for( int i = 0 ; i <= n ; ++ i ) dp[i][0] = i;
        for( int i = 1 ; i <= n ; ++ i ) {
            for( int j = 1 ; j <= m ; ++ j )
                dp[i][j] = ( ( dp[i - 1][j] + C( i + j - 1 , j ) ) % P + ( dp[i][j - 1] - ( C( i + j - 1 , i ) - k[i][j - 1] + P ) % P + P ) % P ) % P;
        }
        cout << dp[n][m] << endl;
    }
    
    
  • 相关阅读:
    关于spring security的若干事情
    .net2005 datagridview 如何获取值改变的单元格的集合??(小弟没有为datagridview添加数据源,也就是说单元格中的数据是手工录入的)
    关于做一个通用打印类的设想,大家谈谈看法
    请教C#,两个类中的变量互访问题
    刚发现了一个问题,关于vs2005 datagridview的,我发现在设计行标头的HeaderCell.Value的时候要是设置RowTemplate.Height 的值>= 17则行标头的那个黑三角就显示出来了,要是小于17就不能显示了,想问问大家,是怎么回事?
    软件架构模式基本概念及三者区别
    以英雄联盟的方式建模,谈对依赖注入(DI)的理解以及Autofac的用法(一)
    适配器模式
    [翻译] WCF运行时架构
    关于synchronized 影响可见性的问题
  • 原文地址:https://www.cnblogs.com/yijan/p/CF1204.html
Copyright © 2020-2023  润新知