zoukankan      html  css  js  c++  java
  • CF Edu Round 71

    CF Edu Round 71

    A There Are Two Types Of Burgers

    贪心随便模拟一下

    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #include<cstdio>
    using namespace std;
    #define MAXN 200006
    int n , m;
    int A[MAXN];
    int b , p , f , h , c;
    int main() {
        int T;cin >> T;
        while( T-- ) {
            cin >> b >> p >> f >> h >> c;
            int res = 0;
            if( h > c ) {
                if( b > 2 * p ) b -= 2 * p , res += p * h;
                else { printf("%d
    ",( b / 2 ) * h); continue; }
                if( b > 2 * f ) printf("%d
    ",res + f * c);
                else printf("%d
    ", res + ( b / 2 ) * c);
            } else {
                if( b > 2 * f ) b -= 2 * f , res += f * c;
                else { printf("%d
    ",( b / 2 ) * c); continue; }
                if( b > 2 * p ) printf("%d
    ",res + p * h);
                else printf("%d
    ", res + ( b / 2 ) * h);
            }
        }
    }
    
    

    B Square Filling

    贪心,从左上角往左往下枚举,如果可以涂就涂,最后判断一下就好了。

    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #include<vector>
    #include<cstdio>
    using namespace std;
    #define MAXN 56
    int A[MAXN][MAXN];
    int n , m;
    bool book[MAXN][MAXN];
    vector<pair<int,int> > ans;
    int main() {
        cin >> n >> m;
        for( int i = 1 ; i <= n ; ++ i )
            for( int j = 1 ; j <= m ; ++ j ) scanf("%d",&A[i][j]);
        for( int i = 1 ; i <= n ; ++ i ) {
            for( int j = 1 ; j <= m ; ++ j ) if( A[i][j] ) {
                if( ( i == n || j == m )  ) if(!book[i][j]){ return puts("-1") , 0; } else continue;
                if( A[i][j] == 1 && A[i + 1][j] == 1 && A[i + 1][j + 1] == 1 && A[i][j + 1] == 1 )
                    book[i][j] = book[i+1][j] = book[i+1][j+1] = book[i][j + 1] = 1 , ans.push_back( make_pair( i , j ) );
                else if( !book[i][j] ) return puts("-1") , 0;
            }
        }
        cout << ans.size() << endl;
        for( int i = 0 ; i < ans.size() ; ++ i )
            printf("%d %d
    ",ans[i].first , ans[i].second);
    }
    
    

    C Gas Pipeline

    随便线性dp一下就好了

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #define MAXN 300006
    #define int long long
    typedef long long ll;
    using namespace std;
    ll dp[MAXN][2] , len;
    char s[MAXN];
    signed main() {
        int T; cin >> T;
        while( T --> 0 ) {
            ll n, a, b;
            scanf("%lld%lld%lld%s", &n, &a, &b , s);
            len = strlen(s);
            dp[0][0] = b, dp[0][1] = 0x3f3f3f3f3f3f3f3f;
            for (int i = 1; i <= len; i++)
                if (s[i - 1] == '1')
                    dp[i][1] = dp[i - 1][1] + a + 2 * b , dp[i][0] = 0x3f3f3f3f3f3f3f3f;
                else
                    dp[i][1] = min( ( a << 1 ) + dp[i - 1][0], dp[i - 1][1] + a) + ( b << 1 ),
                    dp[i][0] = min( a + dp[i - 1][0] , ( a << 1 ) + dp[i - 1][1] ) + b;
            printf("%lld
    ",dp[len][0]);
        }
    }
    
    

    D Number Of Permutations

    容斥一下,总排列数 - 第一个顺序 - 第二个顺序 + 两个都顺序

    计算很简单,用阶乘搞一下就好了

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #include <iostream>
    using namespace std;
    #define P 998244353
    #define MAXN 300006
    #define int long long
    int n;
    pair<int,int> A[MAXN];
    int J[300050]; 
    bool cmp1(pair<int,int> a,pair<int,int> b) {
        return a.first == b.first ? a.second < b.second : a.first < b.first;
    } 
    bool CMP(pair<int,int> a,pair<int,int> b) {
        return a.second < b.second;
    }
    signed main() {
        J[0] = 1; for (int i = 1; i <= 300000; ++i) J[i] = J[i - 1] * 1ll * i % P;
        scanf("%lld", &n);
        for (int i = 1; i <= n; ++i)
            scanf("%lld%lld", &A[i].first, &A[i].second);
        sort(A + 1, A + 1 + n, cmp1);
        int cur = 1 , ans = J[n];
        int l = 0;
        for (int i = 1; i <= n; ++i)
            if (A[i].first != A[i - 1].first) cur *= J[l], l = 1, cur %= P;
            else l++;
        cur *= J[l] , cur %= P , ans -= cur;
        bool flg = 1;
        for (int i = 1; i <= n; ++i)
            if (A[i].second < A[i - 1].second) { flg = 0; break; }
        if (flg) {
            cur = 1 , l = 0;
            for (int i = 1; i <= n; ++i) 
                if (A[i].first != A[i - 1].first || A[i].second != A[i - 1].second) 
                    cur *= J[l], l = 1 , cur %= P;
                else l++;
            cur *= J[l], cur %= P , ans += cur;
        }
        sort(A + 1, A + 1 + n, CMP);
        cur = 1, l = 0;
        for (int i = 1; i <= n; ++i) {
            if (A[i].second != A[i - 1].second)
                cur *= J[l] , cur %= P , l = 1;
            else ++ l;
        }
        cur *= J[l] , cur %= P , ans -= cur;
        printf("%lld
    ", (ans % P + P) % P);
        return 0;
    }
    
    

    E XOR Guessing

    考场上嫖了个ywh的随机。。。

    然而实际上很简单。。

    考虑分成前7位和后7位,前100个数字前7位全部留空,后100个数字后7位全部留空,做完了

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    int pre , aft;
    int main() {
        cout << '?' ;
        for( int i = 1 ; i <= 100 ; ++ i ) cout << ' ' << i;
        cout << endl;
        fflush( stdout );
        cin >> pre;
        cout << '?';
        for( int i = 1 ; i <= 100 ; ++ i ) cout << ' ' << ( i << 7 );
        cout << endl;
        fflush( stdout );
        cin >> aft;
        int res = 0;
        res |= ( pre & ( ( 1 << 8 ) - 1 ) << 7 );
        res |= ( aft & ( 1 << 7 ) - 1 );
        cout << '!' << ' ' <<  res << endl;
        fflush( stdout );
    }
    

    F Remainder Problem

    大水题

    第二种操作,如果$ y > sqrt n $ 直接naive地暴力

    否则,每次一操作后预处理一下 $ y leq sqrt n $的答案

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <iostream>
    typedef long long ll;
    using namespace std;
    #define MAXN 500006
    #define MXBL 730
    int t, x, y;
    ll buc[MAXN] , S[MXBL][MXBL] , res ;
    signed main() {
        int T;cin >> T;
        while( T --> 0 ) {
            scanf("%d%d%d", &t, &x, &y);
            if (t != 1) {
                if (x < MXBL ) printf("%lld
    ", S[x][y]);
                else {
                    res = 0; for (int j = y; j < MAXN; j += x) res += buc[j];
                    printf("%lld
    ", res);
                }
            } else {
                for (int j = 1; j < MXBL; ++j) S[j][x % j] += y;
                buc[x] += y;
            }
        }
    }
    
    

    G Indie Album

    ACAM 好题

    其实自己根本不怎么会acam。。。这题赛后写来顺便学习了一下acam

    当然,考场上很多人都写的广义后缀自动机+树链剖分。

    只是yijan现在还不大会(。。。wtcl

    发现后缀自动机各种板子写多了的带佬们看字符串题都是秒啊。。


    首先对于所有询问串建ac自动机,再把fail树建立出来。

    如果不考虑复杂度,把询问离线,然后对于每一个文本串都在询问的fail树上跑,跑到的节点都+1,然后每个询问在这个串里面出现的次数就是这个串子树的和。

    但是这么做显然复杂度是错的,但是发现这道题给文本串的方式很特殊,所有的文本串也构成了一个树形结构,于是可以考虑dfs这个文本串构成的树,用一种类似增量法的科技,增加一个字符后会多对一个位置+1,而离开dfs时会对这个位置-1,中间统计一下所有关于这个串的答案就可以了。

    单点+,区间查需要一个fenwick tree,复杂度 (O (TlogT))

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<algorithm>
    #include<vector>
    #include<queue>
    using namespace std;
    #define MAXN 400006
    int n , m;
    char ch[MAXN];
     
    int trie[MAXN][26] , fail[MAXN * 26] , ncnt = 0;
    int T[MAXN];
    int dfn;
    void add( int x , int c ) {
        while( x <= dfn ) T[x] += c , x += x & -x;
    }
    int que( int x ) {
        int ret = 0;
        while( x > 0 ) ret += T[x] , x -= x & -x;
        return ret;
    }
    vector< pair<int,int> > ff[MAXN];
    int ins( char* P ) {
        int cur = 0 , len = strlen( P );
        for( int i = 0 ; i < len ; ++ i ) {
            int v = P[i] - 'a';
            if( !trie[cur][v] ) trie[cur][v] = ++ncnt;
            cur = trie[cur][v];
        }
        return cur;
    }
    queue<int> Q;
    vector<int> F[MAXN] , G[MAXN];
    void build(  ) {
        int cur;
        for( int i = 0 ; i < 26 ; ++ i ) if( trie[0][i] )
            Q.push( trie[0][i] ) , fail[trie[0][i]] = 0;
        while( !Q.empty( ) ) {
            cur = Q.front() , Q.pop();
            F[fail[cur]].push_back( cur );
            for( int i = 0 ; i < 26 ; ++ i ) {
                if( trie[cur][i] )
                    fail[trie[cur][i]] = trie[fail[cur]][i] ,
                    Q.push( trie[cur][i] );
                else
                    trie[cur][i] = trie[fail[cur]][i];
            }
        }
    }
    int L[MAXN] , R[MAXN];
    void predfs( int u ) {
        L[u] = ++ dfn;
        for( int i = 0 ; i < F[u].size() ; ++ i ) predfs( F[u][i] );
        R[u] = dfn;
    }
    int ans[MAXN];
    void work( int u , int p ) {
        p = trie[p][ch[u] - 'a'];
        add( L[p] , 1 );
        for( int i = 0 ; i < G[u].size() ; ++ i )
            work( G[u][i] , p );
        for( int i = 0 ; i < ff[u].size() ; ++ i )
            ans[ff[u][i].second] = que( R[ff[u][i].first] ) - que( L[ff[u][i].first] - 1 );
        add( L[p] , -1 );
    }
    char P[MAXN];
    int ffa[MAXN];
    int main() {
        cin >> n;
        for( int i = 1 , t , opt ; i <= n ; ++ i ) {
            scanf("%d ",&opt);
            if( opt == 1 ) { scanf("%c",&ch[i]) , ffa[i] = 0 , G[0].push_back( i ); continue; }
            scanf("%d %c",&t,&ch[i]);
            ffa[i] = t , G[t].push_back( i );
            getchar();
        }
        cin >> m;
        for( int i = 1 , t ; i <= m ; ++ i ) {
            scanf("%d%s",&t,P);
            int x = ins( P );
            ff[t].emplace_back( make_pair( x , i ) );
        }
        build( );
        predfs( 0 );
        for( int i = 1 ; i <= n ; ++ i ) if( !ffa[i] )
            work( i , 0 );
        for( int i = 1 ; i <= m ; ++ i ) printf("%d
    ",ans[i]);
    }
    
    
  • 相关阅读:
    Eclipse 的快捷键
    using的用法
    二进制、八进制、十进制、十六进制之间的转换
    解决重置PostgreSQL 9.6密码的问题
    byte[]数组和int之间的转换
    【2021】IOS技术 UITableViewCell分割线无留白技巧
    【2021】IOS技术:属性观察器(Property Observers)倒计时实现
    【2019】问题记录一:后端获取URL参数的值内加号“+”变成空格“ ”
    【2015】对面向对象的理解
    “退格键”(Backspace)你想退到哪里?比较含退格的字符串
  • 原文地址:https://www.cnblogs.com/yijan/p/cf1207.html
Copyright © 2011-2022 走看看