第五次群赛暨清明节专场

题目链接: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。搜索题。。没写到~

原文地址:https://www.cnblogs.com/hlmark/p/4395291.html