zoukankan      html  css  js  c++  java
  • 第五次群赛暨清明节专场

    题目链接:http://www.kuangbinoj.com:8080/contest.php?cid=1007

    在ACM交流群的第一场群赛,感觉题目还是不错的。

    A : 给出一个 1元1次方程 , 求解

    算是一个模拟题,我做法是将其化成  k1*x + c1  = k2 * x + c2 的形式

    注意下 。 答案有可能是 -0 , 要弄回0 , 然后变量 x可能带数字 ,  k1-k2 可能是0 的情况

    都考虑了的话肯定过了

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <queue>
    using namespace std ;
    const int N = 200010 ;
    typedef long long LL;
    typedef pair<int,int> pii ;
    #define X first
    #define Y second
    char s[N] , x[N] ;
    LL v , flag , sgin , nowk , k[2] , c[2] ;
      
    void Work() {
        if( flag ) {
            if( nowk == 0 ) nowk = 1 ;
            k[v] += sgin*nowk ;
        } else {
            c[v] += sgin*nowk ;
        }
    }
      
    bool check( int i ) {
        if( s[i] == '=' || s[i] == '+' || s[i] == '-' || ( s[i] >= '0' && s[i] <= '9' ) ) return true;
        return false ;
    }
      
    int Run() {
        int _ ; scanf("%d",&_);
        while( _-- ) {
            getchar();
            scanf("%s",s);
            int len = strlen(s);
            v = 0 , flag = 0 ; sgin = 1 , nowk = 0 ;
            for( int i = 0 ; i < 2 ; ++i ) c[i] = k[i] = 0 ;
            for( int i = 0 ; i < len ; ++i ) {
                if( s[i] == '=' ) {
                    Work();
                    sgin = 1 ; nowk = 0 ; flag = 0 ;
                    v++;
                } else if( s[i] == '+' ) {
                    Work();
                    sgin = 1 ; nowk = 0 ; flag = 0 ;
                } else if( s[i] == '-' ) {
                    Work();
                    sgin = -1 ; nowk = 0 ; flag = 0 ;
                } else if( s[i] >= '0' && s[i] <= '9' ) {
                    if( !flag ) nowk = nowk * 10 + ( s[i] - '0' ) ;
                } else {
                    flag = 1 ;
                }
            }
            Work();
            int tot = 0 , f = 0 ;
            for( int i = 0 ; i < len ; ++i ) {
                if( f && ( s[i] == '+' ||  s[i] == '-' ||  s[i] == '=' ) ) {
                    break ;
                } else if( !f && check(i) ) {
                    continue ;
                } else {
                    x[tot++] = s[i] ;
                    x[tot] = 0 ;
                    f = 1 ;
                }
            }
            double ans ;
            int cc = ( c[1] - c[0] ) , kk = ( k[0] - k[1] ) ;
            if( kk == 0 ) ans = 0 ;
            else ans = 1.0 * cc / kk ;
            if( ans == 0 ) ans = 0 ;
            printf("%s=%.3lf
    ",x,ans);
        }
        return 0 ;
    }
    int main() {
        #ifdef LOCAL
            freopen("in.txt","r",stdin);
        #endif // LOCAL
        ios::sync_with_stdio(0);
        return Run() ;
    }
    /**************************************************************
        Problem: 1220
        User: hl_mark
        Language: C++
        Result: 正确
        Time:0 ms
        Memory:1928 kb
    ****************************************************************/
    View Code

    B. 给出一个长是S的数字串, 问划分成 n + 1 分 相乘得到的数字最大是多少 。

    S长度是 40 。 然后就写了一个大数+dp 。

    dp[i][j] 表示分成了 i 分 , 分到第j 个数字得到最大结果是什么 。

    转移就是

             dp[i][j] = max { dp[i][j] , dp[i-1][k] * num( k +1 , j ) [  i - 1 <= k < j ] } ..

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <queue>
    using namespace std ;
    const int N = 200010 ;
    typedef long long LL;
    #define MAXN 9999
    #define mod 10000
    #define MAXSIZE 1010
    #define DLEN 4
    class BigNum {
    private:
        int a[400];
        int len ;
    public:
        BigNum(){ len = 1 ; memset( a , 0 , sizeof a ) ; }
        BigNum(const char *);
        BigNum &operator=(const BigNum &);
        BigNum operator*(const BigNum &)const;
        bool operator > ( const BigNum &T )const ;
        void print();
    };
     
    BigNum::BigNum( const char *s ) {
        int t , k , index , L , i ;
        memset( a , 0 , sizeof a ) ;
        L = strlen(s);
        len = L/DLEN;
        if( L % DLEN ) len++ ;
        index = 0 ;
        for( int i = L - 1 ; i >= 0 ; i -= DLEN ) {
            t = 0 ;
            k = i - DLEN + 1 ;
            if( k < 0 ) k = 0;
            for( int  j = k ; j <= i ; j++ ) {
                t = t*10+s[j]-'0';
            }
            a[index++] = t ;
        }
    }
     
    BigNum BigNum::operator * ( const BigNum &T )const {
        BigNum res ;
        for( int i = 0 ; i < len ; ++i ) {
            int up = 0 ;
            for( int j = 0 ; j < T.len ; ++j ) {
                int tmp = a[i] * T.a[j] + res.a[i+j] + up;
                    res.a[i+j] = tmp % mod ;
                    up = tmp / mod ;
            }
            if( up != 0 )
                res.a[i+T.len] = up ;
        }
        res.len = len + T.len ;
        while( res.a[res.len-1] == 0 && res.len > 1 ) res.len-- ;
        return res ;
    }
     
    bool BigNum::operator > ( const BigNum &T )const {
        int ln ;
        if( len > T.len ) {
            return true ;
        } else if( len == T.len ) {
            ln = len - 1 ;
            while( a[ln] == T.a[ln] && ln > 0 ) ln-- ;
            if( ln >= 0 && a[ln] > T.a[ln] ) return true ;
            else return false ;
        } else {
            return false;
        }
    }
    BigNum &BigNum::operator=( const BigNum &T ){
        int i ;
        len = T.len ;
        memset( a, 0 , sizeof a ) ;
        for( int i = 0 ; i < len ; ++i ) a[i] = T.a[i] ;
        return *this ;
    }
     
    void BigNum::print() {
        int i ;
        printf("%d",a[len-1]);
        for( i = len - 2 ; i >=0 ; --i )
            printf("%04d",a[i]);
        printf("
    ");
    }
     
    BigNum dp[8][44] ;
    int n , m ;
    char ss[44] , s[44];
     
    void toString( int i , int j ) {
        int tot = 0 ;
        for( int y = i ; y <= j ; ++y ) ss[tot++] = s[y] ;
        ss[tot] = 0 ;
    }
     
    void init() {
        for( int i = 0 ; i <= m ; ++i ) {
            for( int j = 0 ; j <= n ; ++j )
            dp[i][j] = "0";
        }
        int tot = 0 ;
        for( int i = 0 ; i < n ; ++i ) {
            ss[tot++] = s[i] ;
            dp[0][i] = ss ;
        }
    }
     
    int Run() {
        while( ~scanf("%d%d",&n,&m)) {
            scanf("%s",s);
            init();
            for( int i = 1 ; i <= m ; ++i ) {
                for( int j = i ; j < n ; ++j ) {
                    for( int k = i - 1 ; k < j ; ++k ) {
                        toString( k + 1 , j ) ;
                        BigNum w = BigNum(ss) ;
                        BigNum tmp = dp[i-1][k] * w ;
                        if( tmp > dp[i][j] ) {
                            dp[i][j] = tmp ;
                        }
                    }
                }
            }
            dp[m][n-1].print();
        }
        return 0 ;
    }
    int main() {
        #ifdef LOCAL
            freopen("in.txt","r",stdin);
        #endif // LOCAL
        ios::sync_with_stdio(0);
        return Run() ;
    }
     
    /**************************************************************
        Problem: 1221
        User: hl_mark
        Language: C++
        Result: 正确
        Time:0 ms
        Memory:2088 kb
    ****************************************************************/
    View Code

    C. 将20个单词进行接龙 , 问能得到最长的单词的长度

    就设一个 dp[st][i] , 表示用了st状态中的单词,最后一个单词是 i 能得到的最长长度 。

    两个单词能够接龙的条件是, 前一个单词的后缀跟后一个单词的后缀相同 。

    有给出第一个单词的首字母..所以我就直接 spfa ..

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <queue>
    using namespace std ;
    const int N = 1<<20 ;
    typedef pair<int,int> pii ;
    #define X first
    #define Y second
    int dp[N][22], n ;
    string s[22] ;
    char start ;
    int ans = 0 ;
    int cal( int x , int y ) {
        int res = -1 ;
        for( int i = s[x].length() - 1 ; i >= 0 ; --i ) {
            bool tag = false ;
            if( s[x].length() - i > s[y].length() ) continue ;
            for( int j = 0 ; j + i < s[x].length() ; ++j ) {
                if( s[x][i+j] != s[y][j] ) break ;
                if( j + i == s[x].length() - 1 ) tag = true ;
            }
            if( tag ) res = max( res , (int)s[y].length() - (int)s[x].length() + i  ) ;
        }
        return res ;
    }
      
    bool inq[N][22] ;
      
    void bfs() {
        queue<pii>que;
        memset( inq , false , sizeof inq ) ;
        memset( dp , 0 , sizeof dp ) ;
      
        for( int i = 0 ; i < n ; ++i ) {
            if( s[i][0] == start ) {
                que.push( pii(1<<i,i) ) ;
                dp[1<<i][i] = s[i].length();
                inq[1<<i][i] = true ;
            }
        }
      
        while( !que.empty() ) {
            int st = que.front().X , ed = que.front().Y ;
            que.pop();
            ans = max( ans , dp[st][ed] );
            inq[st][ed] = false ;
            for( int i = 0 ; i < n ; ++i ) {
                if( st&(1<<i)  ) continue ;
                int w = cal( ed , i ) ;
                if( w == -1 ) continue ;
                int vst = st|(1<<i) ;
                if( dp[vst][i] < dp[st][ed] + w ) {
                    dp[vst][i] = dp[st][ed] + w ;
                    if( !inq[vst][i] ) {
                        inq[vst][i] = true ;
                        que.push( pii(vst,i) );
                    }
                }
            }
        }
    }
    int Run() {
        while( cin >> n ) {
            for( int i = 0 ; i < n ; ++i )
                cin >> s[i] ;
            cin >> start ;
            ans = 0 ; bfs();
            cout << ans << endl ;
        }
        return 0 ;
    }
    int main() {
        #ifdef LOCAL
            freopen("in.txt","r",stdin);
        #endif // LOCAL
        ios::sync_with_stdio(0);
        return Run() ;
    }
    View Code

    D. 一个很水的整数划分

    将整数T分成N份,每份里面必须有数不能空,且不能有相同的分法(不考虑顺序)

    dp[i][j]表示 i 分成了 j 分的个数 。

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    using namespace std ;
    const int N = 22 ;
    int dp[205][10] , n , k ;
    int Run() {
        while( cin >> n >> k ) {
            memset( dp , 0 ,sizeof dp );
            dp[0][0] = 1 ;
            for( int i = 1 ; i <= n ; ++i ) {
                for( int j = i ; j <= n ; ++j ) {
                    for( int z = 1 ; z <= k ; ++z ) {
                        dp[j][z] += dp[j-i][z-1] ;
                    }
                }
            }
            cout << dp[n][k] << endl ;
        }
        return 0 ;
    }
    int main() {
        #ifdef LOCAL
            freopen("in.txt","r",stdin);
        #endif // LOCAL
        ios::sync_with_stdio(0);
        return Run() ;
    }
    View Code

    E . 最短路变形 。

    http://www.cnblogs.com/hlmark/p/4395271.html

    #include <cstdio>
    #include <cstring>
    #include <queue>
    #include <iostream>
    #include <map>
    #include <stack>
    using namespace std ;
    typedef pair<int,int> pii ;
    #define X first
    #define Y second
    const int N = 1010 ;
    const int inf = 1e9+7 ;
    typedef long long LL;
    int n , xx[N] , pre[N] , ww[N] , tot ;
    
    vector<pii>g[N];
    
    
    struct node {
        int a , c , d , id ;
        node(){};
        node( int a , int c , int d , int id ):a(a),c(c),d(d),id(id){}
        bool operator < ( const node &A ) const {
            if( d != A.d ) return d > A.d ;
            else if( c != A.c ) return c > A.c ;
            else {
                stack<int>s1 , s2; int id1 = id , id2 = A.id ;
                while( id1 != -1 ) { s1.push( xx[id1] ); id1 = pre[id1] ; }
                while( id2 != -1 ) { s2.push( xx[id2] ); id2 = pre[id2] ; }
                while( !s1.empty() ) {
                    int a = s1.top() ; s1.pop() ;
                    int b = s2.top() ; s2.pop() ;
                    if( a > b ) return true ;
                }
                return false ;
            }
        }
    };
    int bestpath[N] , bestcnt , bestcost ;
    int tmppath[N] , tmpcnt , tmpcost ;
    
    
    void Choose_best( int id , int cnt ) {
        if( tmpcost > bestcost ) return  ;
        stack<int>s ;
        while( id != -1 ) { s.push( xx[id] ); id = pre[id] ; }
        tmpcnt = 0 ;
        while( !s.empty() ) { tmppath[tmpcnt++] = s.top() ; s.pop() ; }
    
        if( tmpcost < bestcost ) {
            bestcnt = tmpcnt ;
            bestcost = tmpcost ;
            for( int i = 0 ; i < tmpcnt ; ++i ) bestpath[i] = tmppath[i] ;
            return ;
        }
        if( cnt > bestcnt ) return ;
        else if( cnt < bestcnt ) {
            bestcnt = tmpcnt ;
            for( int i = 0 ; i < tmpcnt ; ++i ) bestpath[i] = tmppath[i] ;
        } else {
            for( int i = 0 ; i < tmpcnt ; ++i ) {
                if( bestpath[i] > tmppath[i] ) {
                    for( int j = i ; j < bestcnt ; ++j ) {
                        bestpath[j] = tmppath[j] ;
                    }
                } else if ( bestpath[i] < tmppath[i] ) {
                    break ;
                }
            }
        }
    }
    
    int dis[N] ;
    
    void dij() {
        memset( dis , 0x3f , sizeof dis );
        priority_queue<node>que;
        tot = 0 ; xx[tot] = 0 , pre[tot] = -1 ; tot++ ;
        que.push( node(0,0,0,tot-1) );
        dis[0] = 0 ;
        while( !que.empty() ) {
            int u = que.top().a , cnt = que.top().c , cost = que.top().d , id = que.top().id ;
            que.pop();
            if( cost > dis[u] ) continue ;
            if( u == 1 ) {
                if( dis[u] ) {
                    tmpcost = dis[u] ;
                    Choose_best( id , cnt );
                }
                return ;
            }
            for( int i = 0 ; i < g[u].size() ; ++i ) {
                int v = g[u][i].X , w = ww[g[u][i].Y] ;
                if( dis[v] > dis[u] + w ) {
                    dis[v] = dis[u] + w ;
                    xx[tot] = v ; pre[tot] = id ; tot++;
                    que.push( node( v , cnt+1 , dis[v] , tot - 1 ) ) ;
                }
            }
        }
    }
        
    void Gao() {
        dij();
        for( int i = 0 ; i < n ; ++i ) {
            int cc = ww[i] ; ww[i] = 0 ;
            dij();
            for( int j = i + 1 ; j < n ; ++j ) {
                int dd = ww[j] ; ww[j] = 0 ;
                dij(); ww[j] = dd ;
            }
            ww[i] = cc ;
        }
        for( int i = 0 ; i < bestcnt ; ++i ) cout << bestpath[i] << ' ' ;
        cout << bestcost << endl ;
    }
    
    int Run() {
        while( cin >> n && n ) {
            bestcost = bestcnt = inf ;
            for( int i = 0 ; i < N ; ++i ) g[i].clear();
            for( int i = 0 ; i < n ; ++i ) {
                int u , v , w ; cin >> u >> v >> w ;
                ww[i] = w ;
                g[u].push_back(pii(v,i));
                g[v].push_back(pii(u,i));
            }
            Gao();
        }
        return 0 ;
    }
    
    int main() {
        #ifdef LOCAL
            freopen("in.txt","r",stdin);
        #endif // LOCAL
        ios::sync_with_stdio(0);
        return Run();
    }
    View Code

    F. 给出两个字符串,问两个串的循环节中有多少个是一样的。

    貌似有其他KMP什么的解法。

    我做法是先 O( sqrt n ) 把串长的约数分解出来 。

    然后暴力一下那些约数的循环节是否可行的 。 最坏情况就是所有都不可行 。 O( n * sqrt(n) )  ,  n 是 1e5 不卡根号

    然后最后判下两个串可行的循环节是否相同就OK了 ~

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <queue>
    #include <algorithm>
     
    using namespace std ;
    const int N = 200010 ;
    typedef long long LL;
    typedef pair<int,int> pii ;
    char s[2][N] ;
    int n , fac[N] , tot ;
     
    void Gao() {
        tot = 0 ;
        for( int i = 1 ; i * i <= n ; ++i ) {
            if( n % i == 0 ) {
                fac[tot++] = i ;
                if( n / i != i ) fac[tot++] = n / i ;
            }
        }
        sort( fac , fac + tot ) ;
    }
     
    bool check( int x , char *str ) {
        for( int i = x ; i < n ; ++i ) {
            if( str[i] != str[i%x] ) {
                return false ;
            }
        }
        return true ;
    }
     
    bool check2( int x ) {
        for( int i = 0 ; i < x ; ++i ) {
            if( s[0][i] != s[1][i] ) return false ;
        }
        return true ;
    }
     
    bool vis[N] , can[N][2];
     
    void Work( int v ) {
        memset( vis , false , sizeof vis );
        for( int i = 0 ; i < tot ; ++i ) if( !vis[i] ) {   // O( sqrt(n) );
            if( check( fac[i] , s[v] ) ) {         // O( n )
                can[ fac[i] ][v] = true ;
                for( int j = i + 1 ; j < tot ; ++j ) if( fac[j] % fac[i] == 0 ) {
                    can[ fac[j] ][v] = vis[j] = true ;
                }
            }
        }
    }
     
    int Run() {
        while( ~scanf("%s%s",s[0],s[1])) {
            memset( can , false , sizeof can );
            n = strlen(s[0]);
            Gao();
             Work(0);
            n = strlen(s[1]);
            Gao();
            Work(1);
            int ans = 0 ;
            for( int i = 0 ; i < tot ; ++i ) if( can[ fac[i] ][0] && can[ fac[i] ][1] && check2( fac[i] ) ) {
                ans++ ;
            }
            printf("%d
    ",ans);
        }
        return 0 ;
    }
    int main() {
        #ifdef LOCAL
            freopen("in.txt","r",stdin);
        #endif // LOCAL
        ios::sync_with_stdio(0);
        return Run() ;
    }
    View Code

    G。搜索题。。没写到~

  • 相关阅读:
    从HDFS下载文件到本地
    oracle jdbc jar包异常
    spring jdbctemplate 启动报错(oracle驱动bug)
    solr搜索异常
    jdbc 处理Clob
    Wavosaur音频编辑软件: 功能专业,体积超小(500KB)
    isa server 2004中找不到HTTP过滤选项。
    cisco pix logging facility含义
    IPSec基础-密钥交换和密钥保护
    cisco 831 使用 SDM
  • 原文地址:https://www.cnblogs.com/hlmark/p/4395291.html
Copyright © 2011-2022 走看看