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
    ****************************************************************/

     

  • 相关阅读:
    Android——DEBUG 堆栈
    mycat读写分离与主从切换
    【測试工具】一个将Unix时间转换为通用时间的工具
    jQuery:多个AJAX/JSON请求相应单个回调
    iOS开发中经常使用的Xcode插件
    JAVA学习第二十六课(多线程(五))- 多线程间的通信问题
    我的mac OSX bash_profile文件
    angular学习(二)—— Data Binding
    python 读取grib grib2
    linux获取内存、cpu、负载、网口流量、磁盘信息
  • 原文地址:https://www.cnblogs.com/yefeng1627/p/3068773.html
Copyright © 2011-2022 走看看