zoukankan      html  css  js  c++  java
  • 【8.16校内测试】【队列】【数学】【网络流/二分图最大匹配】

    在一个队列中一次加入每一个字符,每次更新当前队列中的状态,当满足存在26个不同字符时,更新答案,删除队首。

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<queue>
    #define RG register
    using namespace std;
    
    char s[2000005];
    int len, nex[2000005], flag[30];
    int q[2000005];
    
    int main ( ) {
        freopen ( "str.in", "r", stdin );
        freopen ( "str.out", "w", stdout );
        scanf ( "%s", s );
        len = strlen ( s );
        for ( RG int i = 0; i < len; i ++ )
            flag[s[i]-'A'] = 1;
        int fl = 0;
        for ( RG int i = 0; i < 26; i ++ )    
            if ( !flag[i] ) {
                fl = 1; break;
            }
        if ( fl ) {
            printf ( "QwQ" );     return 0;
        }
        int num = 0, ans = 0x3f3f3f3f, h = 0, t = 0;
        memset ( flag, 0, sizeof ( flag ) );
        for ( RG int i = 0; i < len; i ++ ) {
            q[++t] = s[i]-'A'; flag[s[i]-'A'] ++;
            if ( flag[s[i]-'A'] == 1 ) num ++;
            while ( t-h && num == 26 ) {
                ans = min ( ans, t-h );
                int x = q[h+1]; h ++;
                flag[x] --;
                if ( !flag[x] ) num --;
            }
        }
        printf ( "%d", ans );
    }

    一开始想的分解质因数,再通过每个质因子的个数来判断是否成立,可是一开始就错了...以为1e9开方是1e3...

    方法是先将x和y乘起来,因为题目有一个性质,他们的乘积一定是一个数的3次方,设这个数为k,因为x和y中每次游戏要不是有一个k1值,要不是有两个,所以x和y必然可以整除k。三个判断条件即可。【注意】二分求k值时不能让k大于1e6,三方爆long long。

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #define ll long long
    using namespace std;
    
    ll x, y;
    int num1[400001], num2[400001];
    int prime[400001], tot, isnot[400001];
    
    void read ( ll &x ) {
        x = 0; char ch = getchar ( ); int t = 1;
        while ( ch > '9' || ch < '0' ) {
            if ( ch == '-' ) t = -1; ch = getchar ( );
        }
        while ( ch >= '0' && ch <= '9' ) {
            x = x * 10 + ch - '0';
            ch = getchar ( );
        }
        x = x * t;
    }
    
    inline int gcd ( int a, int b ) {
        return b == 0 ? a : gcd ( b, a % b );
    }
    
    ll erfen ( ll qwq ) {
        ll l = 1, r = min ( sqrt ( qwq ), 1e6 ), res;
        while ( l <= r ) {
            ll mid = ( l + r ) >> 1;
            if ( mid * mid * mid <= qwq ) {
                l = mid + 1; res = mid;
            } else r = mid - 1;
        }
        return res;
    }
    
    int main ( ) {
        freopen ( "game.in", "r", stdin );
        freopen ( "game.out", "w", stdout );
        int T;
        scanf ( "%d", &T );
        while ( T -- ) {
            int fl = 0;
            read ( x ); read ( y );
            ll g = 1ll * x * y;
            ll qwq = erfen ( g );
            if ( qwq * qwq * qwq != g ) fl = 1;
            if ( x % qwq != 0 || y % qwq != 0 ) fl = 1;
            if ( fl ) printf ( "No
    " );
            else printf ( "Yes
    " );
        }
        return 0;
    }

    比较经典的一道题,分别把按行放木板和按列放木板给每一块泥地标号,可以连着放的号数一样。把每一个泥地的行号连向列号,跑最小割或者最大匹配即可。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    #define inf 0x3f3f3f3f
    using namespace std;
    
    int r, c;
    char a[55][55];
    int num1[55][55], num2[55][55], cnt1, cnt2, s, t;
    
    int stot = 1, h[10005], tov[200005], nex[200005], f[200005], hh[10005];
    void add ( int u, int v, int ff ) {
        tov[++stot] = v;
        f[stot] = ff;
        nex[stot] = h[u];
        h[u] = stot;
        
        tov[++stot] = u;
        f[stot] = 0;
        nex[stot] = h[v];
        h[v] = stot;
    }
    
    int dep[1005], vis[1005];
    queue < int > q;
    bool bfs ( ) {
        memset ( dep, 0, sizeof ( dep ) );
        memset ( vis, 0, sizeof ( vis ) );
        q.push ( s );    vis[s] = 1;
        while ( !q.empty ( ) ) {
            int u = q.front ( ); q.pop ( );
            for ( int i = h[u]; i; i = nex[i] ) {
                int v = tov[i];
                if ( !vis[v] && f[i] ) {
                    dep[v] = dep[u] + 1;
                    vis[v] = 1;
                    q.push ( v );
                }
            }
        }
        return vis[t];
    }
    
    int dfs ( int u, int delta ) {
        if ( u == t ) return delta;
        int res = 0;
        for ( int i = hh[u]; i && delta; i = nex[i] ) {
            int v = tov[i];
            if ( dep[v] == dep[u] + 1 && f[i] ) {
                int dd = dfs ( v, min ( f[i], delta ) );
                f[i] -= dd;
                f[i^1] += dd;
                delta -= dd;
                res += dd;
                hh[u] = i;
            }
        }
        return res;
    }
    
    void debug ( ) {
        for ( int i = 0; i < r; i ++ ) {
            for ( int j = 0; j < c; j ++ )
                printf ( "%d ", num1[i][j] );
            cout << endl;
        }
        cout << endl;
        for ( int i = 0; i < r; i ++ ) {
            for ( int j = 0; j < c; j ++ )
                printf ( "%d ", num2[i][j] );
            cout << endl;
        }
    }
    
    int main ( ) {
        freopen ( "cover.in", "r", stdin );
        freopen ( "cover.out", "w", stdout );
        scanf ( "%d%d", &r, &c );
        for ( int i = 0; i < r; i ++ )
            scanf ( "%s", a[i] );
        for ( int i = 0; i < r; i ++ )
            for ( int j = 0; j < c; j ++ ) {
                if ( j != 0 && a[i][j] == '*' && a[i][j-1] == '*' )     num1[i][j] = num1[i][j-1];
                else if ( a[i][j] == '*' ){
                    cnt1 ++;    num1[i][j] = cnt1;
                }
                if ( i != 0 && a[i][j] == '*' && a[i-1][j] == '*' )     num2[i][j] = num2[i-1][j];
                else if ( a[i][j] == '*' ){
                    cnt2 ++;     num2[i][j] = cnt2;
                }
            }
        //debug ( );
        for ( int i = 0; i < r; i ++ )
            for ( int j = 0; j < c; j ++ )
                if ( a[i][j] == '*' ) {
                    //printf ( "%d->%d+%d
    ", num1[i][j], num2[i][j], cnt1 );
                    add ( num1[i][j], num2[i][j] + cnt1, 1 );
                }
        s = 0, t = cnt1+cnt2+1;
        for ( int i = 1; i <= cnt1; i ++ )
            add ( s, i, 1 );
        for ( int i = 1; i <= cnt2; i ++ )
            add ( i + cnt1, t, 1 );
        int ans = 0;
        while ( bfs ( ) ) {
            for ( int i = 0; i <= cnt1 + cnt2 + 1; i ++ )
                hh[i] = h[i];
            ans += dfs ( s, 0x3f3f3f3f );
        }
        printf ( "%d", ans );
        return 0;
    }
  • 相关阅读:
    用智慧明辨之
    做一个成功的软件架构师需要哪些素质?
    如何成为一名优秀的产品经理
    项目管理中的冲突管理
    .Net 缓存依赖详解
    从程序制作到构架制作
    如何做好一名软件团队的领导者
    需求变更的代价
    页面缓存的实现
    项目风险盘点
  • 原文地址:https://www.cnblogs.com/wans-caesar-02111007/p/9487069.html
Copyright © 2011-2022 走看看