zoukankan      html  css  js  c++  java
  • 201356 训练赛总结

    训练赛链接: http://www.acmore.net/contest.php?cid=1013

    Problem A: Yard

    题意:  n*m的格子,有树与空地,要求每个位置上下左右树的数量为偶数.求拔除与种植最小花费.

    解法: 状态压缩, 第一行状态确定后,则所有行都确定. 然后枚举第一行状态,取个最小值即可.

    View Code
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    using namespace std;
     
     
    const int inf = 0x3f3f3f3f;
     
    char A[110][110];
    int B[110][110];
    int a[110][110];
     
    int n, m, res;
     
    void gao(int &cnt){
        int mark = 0;       
        for(int i = 0; i < m; i++ ){
            if( i == 0 ){
                if( a[0][i+1] ) mark |= (1<<i);   
            }
            else if( i == m-1 ){
                if( a[0][i-1] ) mark |= (1<<i);   
            }
            else{
                mark |= ((a[0][i-1]+a[0][i+1])&1)<<i;
            }   
        }
         
        for(int i = 1; i < n; i++ ){
            // a[][]    
            for(int j = 0; j < m; j++){
                a[i][j] = mark&(1<<j) ? 1 : 0;
                if( a[i][j] != B[i][j] ){
                    if(++cnt > res) return;
                }   
            }   
            // status           
            mark = 0;   
            for(int j = 0; j < m; j++){
                if( j == 0 ) mark |= ((a[i-1][j]+a[i][j+1])&1); 
                else if(j == m-1) mark |= ((a[i][j-1]+a[i-1][j])&1)<<j;
                else mark |= ((a[i][j-1]+a[i-1][j]+a[i][j+1])&1)<<j;
            }   
        }
        if( mark == 0 ) res = min( res, cnt );
    }
    int solve(){
        int Mark = (1<<m)-1 ;
        res = inf;
        for(int mark = 0; mark <= Mark; mark++){
            int cnt = 0;    
            for(int i = 0; i < m; i++){
                a[0][i] = (mark&(1<<i))?1:0;
                cnt += (a[0][i]!=B[0][i]);  
            }   
            gao( cnt );
        }   
        printf("%d\n", res);
    }
    int main(){
        while( scanf("%d%d",&m,&n) != EOF){
            for(int i = 0; i < m; i++)
                scanf("%s", A[i] );
            for(int i = 0; i < n; i++){ // col
                for(int j = 0; j < m; j++){ //  row
                    if( A[j][i] == '#' ) B[i][j] = 1;
                    else    B[i][j] = 0;
                }   
            }   
            solve();    
        }       
        return 0;
    }

    Problem B: ZZB的数学作业

    题意: “把一个正整数M分成P个不超过K的正整数的和,满足分成的数不是N的倍数,并且P也不是N的倍数,求这样的P最小是多少?”

    解法: 判定.  看了AC代码觉得好神奇. 有些地方不太明白为什么可以这样判定,感脚不严谨.,,,先贴份AC代码吧.

    View Code
    #include<cstdio>
    
    typedef long long LL;
    
    LL n, m, k;
    int main(){
        while( scanf("%lld%lld%lld", &n,&m,&k) != EOF){
            if(n == 1){ printf("-1\n"); continue; }        
            if((n==2) && (m%2==0) ){ printf("-1\n"); continue; }
            if((m%n==0) && (k==1) ){ printf("-1\n"); continue; }    
            k = k>m?m:k;    
            while( k%n == 0 ) k--;
            LL cnt = m/k;
            LL left = m%k;
            if( left == 0 ){
                if(cnt%n == 0) cnt++;
            }    
            else{
                cnt++;    
                if(left%n == 0){
                    if( (k-1)%n == 0 ) cnt++;    
                }    
                if(cnt%n == 0) cnt++;
            }    
            printf("%lld\n", cnt);    
        }
        return 0;
    }

    Problem C: 爱情测试

    题意: 给出前三项a1a2a3,以及要求的项的编号n,并且数列{an}只可能是等差数列或者是首项为1的等比数列,要求A输出第n项模100007后的值。

    解法:  判定下,然后根据等差或等比计算即可.

    View Code
    #include <iostream>
    #include <cmath>
    #include <cstring>
    #include <cstdio>
    #include <string>
    #include <stdlib.h>
    #include <algorithm>
    using namespace std;
    typedef long long LL;
    const LL Mod= 100007;
    LL a, b, c, n, d, q, ans; 
    LL M_M( LL a, LL b )
    {
        LL res=0, t=a;
        while( b ){
            if( b&1 )res=(res+t)%Mod;
            t=(t+t)%Mod;
            b>>=1;
        }
        return res;
    }
    LL P_M( LL a, LL b )
    {
        LL res=1, t=a;
        while( b ){
            if( b&1 )res*=t, res%=Mod;
            t*=t, t%=Mod;
            b>>=1;
        }
        return res;
    }
    int cc( int d, int n )
    {
        return (a+M_M(d, n-1))%Mod; 
    }
    int bb( int q, int n )
    {
        return (a*P_M( q, n-1 ))%Mod;
    }
    int main( )
    {
        while( scanf("%lld%lld%lld%lld", &a, &b, &c, &n)==4 ){
            if( a-b==b-c ){
                d=b-a;
                ans=cc(d, n);
            }
            else{
                q=b/a;
                 
                ans=bb( q, n );
            }
            printf("%lld\n", ans);
        }
        return 0;
    }
     
    /**************************************************************
        Problem: 1518
        User: yefeng1627
        Language: C++
        Result: Accepted
        Time:0 ms
        Memory:1432 kb
    ****************************************************************/

    Problem D: 除草

    题意:  很长...

    解法: 不会. 

    Problem E: 友谊圈(Easy)

    题意:  求一个最长上升序列, 要求 ai -aj >= i-j . 

    解法:  因为有相对位置的影响,  预处理可以将 ai - i, 这样就消除了相对位置影响,就可以直接做一个最长上升子序列,即可. 注意 ai > 0. 

    因为这里 N = 1e5, 需要一个 O(NlogN)的算法,  通过保存当前长度最小, 然后二分查找即可,实现 NlogN.

    有个地方需要注意的是, 因为我们令 ai-i,去掉了相对位置影响,则找LIS时,即可高度相同。所以 idx[m] <= x 。

    View Code
    #include<cstdio>
     
    const int N = 200010, inf = 0x3f3f3f3f;
     
    int n, ln, a[N], f[N] = {0,1};
     
    int find(int x){
        int l = 0, r = ln, m, res;
        while( l <= r ){
            m = (l+r)>>1;
            //printf("l = %d, r = %d, m = %d\n", l, r, m ); 
            if( f[m] <= x ) (res=m),(l=m+1);
            else    r = m-1;
            //printf("l = %d, r = %d\n", l, r );    
        }
        return res;
    }
    int main(){
        scanf("%d", &n);
        for(int i = 1; i <= n; i++){
            scanf("%d", &a[i]);
            a[i] -= i;
        }
        f[0] = -inf; ln = 0;
        for(int i = 1; i <= n; i++)
            if( a[i] >= 0 ){
                int t = find(a[i])+1;
                f[t] = a[i];
                if(t > ln) ln = t;
            }
        printf("%d\n", ln );
        return 0;
    }
    /**************************************************************
        Problem: 1523
        User: yefeng1627
        Language: C++
        Result: Accepted
        Time:7 ms
        Memory:2476 kb
    ****************************************************************/

    Problem F: [USACO 1.5.3]特殊的质数肋骨

    题意:  找出长度为 N ,其前缀都为素数的所有数.

    解法: 搜索, 过程中判定, 判定用开根号的方式.即可

    View Code
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    using namespace std;
     
     
    int n;
     
    bool legal(int x){
        if( x == 1 ) return false;  
        for(int i = 2; i*i <= x; i++)
            if( x%i == 0 ) return false;
        return true;
    }
     
    void dfs(int t, int x){
        if( t == n ){
            printf("%d\n",x);   
            return; 
        }
        for(int i = 0; i <= 9; i++){
            int tmp = x*10+i;
            if( legal(tmp) )
                dfs( t+1, tmp );    
        }
    } 
    int main(){
        while( scanf("%d",&n) != EOF){
            for(int i = 1; i <= 9; i++){
                if( legal(i) ){
                    dfs( 1, i );    
                }   
            }           
        }   
        return 0;
    }
    /**************************************************************
        Problem: 1075
        User: yefeng1627
        Language: C++
        Result: Accepted
        Time:0 ms
        Memory:916 kb
    ****************************************************************/

    Problem G: [USACO 1.4.4]母亲的牛奶

    题意: 农民约翰有三个容量分别是A,B,C升的桶,A,B,C分别是三个从1到20的整数,最初,A和B桶都是空的,而C桶是装满牛奶的。有时,约翰把牛奶从一个桶倒到另一个桶中,直到被灌桶装满或原桶空了。当然每一次灌注都是完全的。由于节约,牛奶不会有丢失。写一个程序去帮助约翰找出当A桶是空的时候,C桶中牛奶所剩量的所有可能性。

    解法: BFS搜索, 模型转换, {a,b,c},然后模拟转换过程,标记. 

    View Code
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<queue>
    #include<algorithm>
     
    using namespace std;
     
    int A, B, C;
    bool vis[25][25][25];
     
    struct node{
        int a,b,c;
    }pre,nxt;
     
    queue<node>Q;
     
    void solve(){
     
        pre.a = 0, pre.b = 0, pre.c = C;
        while( !Q.empty() ) Q.pop();
        Q.push( pre );
        vis[0][0][C] = true;
        while( !Q.empty() ){
            pre = Q.front(); Q.pop();
             
            int a = pre.a, b = pre.b, c = pre.c;
            if( a > 0 ){
                if( b < B ){
                    nxt.a = a-min(a,(B-b)); 
                    nxt.b = b+min(a,(B-b)); 
                    nxt.c = c;  
                    if( !vis[nxt.a][nxt.b][nxt.c] )
                        Q.push( nxt ), vis[nxt.a][nxt.b][nxt.c] = true;
                }   
                if( c < C ){
                    nxt.a = a-min(a,(C-c));
                    nxt.b = b;
                    nxt.c = c+min(a,(C-c));
                    if( !vis[nxt.a][nxt.b][nxt.c] )
                        Q.push( nxt ), vis[nxt.a][nxt.b][nxt.c] = true;
                }   
            }
            if( b > 0 ){
                if( a < A ){
                    nxt.a = a+min(b,(A-a));
                    nxt.b = b-min(b,(A-a));
                    nxt.c = c;
                    if( !vis[nxt.a][nxt.b][nxt.c] )
                        Q.push( nxt ), vis[nxt.a][nxt.b][nxt.c] = true;
                }
                if( c < C ){
                    nxt.a = a;
                    nxt.b = b-min(b,(C-c));
                    nxt.c = c+min(b,(C-c));
                    if( !vis[nxt.a][nxt.b][nxt.c] )
                        Q.push( nxt ), vis[nxt.a][nxt.b][nxt.c] = true;
                }
            }   
            if( c > 0 ){
                if( a < A ){
                    nxt.a = a+min(c,(A-a)); 
                    nxt.b = b;
                    nxt.c = c-min(c,(A-a));
                    if( !vis[nxt.a][nxt.b][nxt.c] )
                        Q.push( nxt ), vis[nxt.a][nxt.b][nxt.c] = true;
                }
                if( b < B ){
                    nxt.a = a;
                    nxt.b = b+min(c,(B-b));
                    nxt.c = c-min(c,(B-b));
                    if( !vis[nxt.a][nxt.b][nxt.c] )
                        Q.push( nxt ), vis[nxt.a][nxt.b][nxt.c] = true;
                }
            }   
        }
    }
    int main(){
        while( scanf("%d%d%d",&A,&B,&C) != EOF){
            memset( vis, 0, sizeof(vis) );
            solve();
            bool tmp[25];
            memset(tmp,0,sizeof(tmp));
            for(int b = 0; b <= B; b++)
                for(int c = 0; c <= C; c++)
                    tmp[c] |= vis[0][b][c];
            bool flag = false;  
            for(int i = 0; i <= C; i++)
                if( tmp[i] ){
                    if( !flag ) printf("%d",i), flag =true;     
                    else printf(" %d",i);
                }   
            puts("");
        }
        return 0;
    }
    /**************************************************************
        Problem: 1074
        User: yefeng1627
        Language: C++
        Result: Accepted
        Time:0 ms
        Memory:1032 kb
    ****************************************************************/

    Problem H: [USACO 1.4.2]时钟

    题意: 3*3的矩阵, 有10条规则,转换, 问最短的路径转换到要求状态.

    解法: 还是一样BFS搜索, 使用标记. 处理有点麻烦. 

    View Code
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    using namespace std;
     
    const int N = (int)5e5+10;
     
    bool vis[4][4][4][4][4][4][4][4][4];
    char mp[10];
    bool flag;
    char b[9][9];
     
    struct Node{
        char p[10], kind;
        int f;
    }Q[N], cur;
     
    void init(){
        memset(b,0,sizeof(b));
        b[0][0]=b[0][1]=b[0][3]=b[0][4]=1;
        b[1][0]=b[1][1]=b[1][2]=1;
        b[2][1]=b[2][2]=b[2][4]=b[2][5]=1;
        b[3][0]=b[3][3]=b[3][6]=1;
        b[4][1]=b[4][3]=b[4][4]=b[4][5]=b[4][7]=1;
        b[5][2]=b[5][5]=b[5][8]=1;
        b[6][3]=b[6][4]=b[6][6]=b[6][7]=1;
        b[7][6]=b[7][7]=b[7][8]=1;
        b[8][4]=b[8][5]=b[8][7]=b[8][8]=1;
    }
    void gao(char *c ){
        vis[c[0]][c[1]][c[2]][c[3]][c[4]][c[5]][c[6]][c[7]][c[8]] = true;
    }
    bool legal(char *c){
        if(vis[c[0]][c[1]][c[2]][c[3]][c[4]][c[5]][c[6]][c[7]][c[8]]) 
            return false;
        return true;
    }
    bool over(char *c){
        if( vis[3][3][3][3][3][3][3][3][3] ) return true;
        return false;
    }
    int solve(){    
        memset( vis, 0, sizeof(vis));
        int l = 0, r = 0;   
        memcpy( Q[r].p, mp, 9*sizeof(char)); 
        Q[r].f = -1; Q[r++].kind = -1;
        gao( mp );  
        while( l < r ){
            cur = Q[l];
            if( over(cur.p) ) return l;     
             
            for(int i = 0; i < 9; i++){
                Node tmp = cur; 
                for(int j = 0; j < 9; j++){
                    tmp.p[j] = (tmp.p[j]+b[i][j])%4;    
                }   
                if( legal(tmp.p) ){
                    gao( tmp.p );
                    tmp.f = l; tmp.kind = i+1;  
                    Q[r++] = tmp;
                    if( over(tmp.p) ) return r-1;   
                }   
            }
            l++;    
        }
    }
    void output(int d){
        if( Q[d].f == -1 ) return;
        output( Q[d].f );
        if( flag ) flag = false, printf("%d",Q[d].kind);
        else printf(" %d", Q[d].kind );
    }
    int main(){
        init(); 
        while( scanf("%d%d%d",&mp[0],&mp[1],&mp[2]) != EOF){
            scanf("%d%d%d",&mp[3],&mp[4],&mp[5]);
            scanf("%d%d%d",&mp[6],&mp[7],&mp[8]);
            for(int i = 0; i < 9; i++)
                mp[i] = mp[i]/3 - 1;
            int d = solve();
            flag = true;    
            output(d);
            puts("");   
        }   
        return 0;
    }
    /**************************************************************
        Problem: 1072
        User: yefeng1627
        Language: C++
        Result: Accepted
        Time:85 ms
        Memory:8984 kb
    ****************************************************************/

     

  • 相关阅读:
    [ERR] Node 10.211.55.8:7001 is not empty. Either the node already knows other nodes (check with CLUSTER NODES) or contains some key in database 0.
    PAT A1137 Final Grading (25 分)——排序
    PAT A1136 A Delayed Palindrome (20 分)——回文,大整数
    PAT A1134 Vertex Cover (25 分)——图遍历
    PAT A1133 Splitting A Linked List (25 分)——链表
    PAT A1132 Cut Integer (20 分)——数学题
    PAT A1130 Infix Expression (25 分)——中序遍历
    PAT A1142 Maximal Clique (25 分)——图
    PAT A1141 PAT Ranking of Institutions (25 分)——排序,结构体初始化
    PAT A1140 Look-and-say Sequence (20 分)——数学题
  • 原文地址:https://www.cnblogs.com/yefeng1627/p/3068773.html
Copyright © 2011-2022 走看看