zoukankan      html  css  js  c++  java
  • 训练赛20160417 题解

    训练赛20160417
    5:00:00
     
     
    Current Time: 2016-04-17 21:00:48 Contest Type: Public
    Start Time: 2016-04-17 12:00:00 Contest Status: Ended
    End Time: 2016-04-17 17:00:00 Manager: hrbustacm

    ————————————————————————————————————————————————————————————————————————————————————————————

    ————————————————————————————————————————————————————————————————————————————————————————————

    ————————————————————————————————————————————————————————————————————————————————————————————

    今天比赛好算正常,不过赛后补题很是心酸,尼玛-------》》》》K题,比赛时和队友一起完成了这道题,java大数,样例都过了,不过还是没过,赛后看的题解,发现没什么区别,找了将近一个小时,没找到错误,我和队友放弃,吃饭去了,吃完回来我继续做,最后没办法了,。照着答案敲一遍,还是没对,尼玛,提交20.30次,现在都没过,,,,,,,,,,,脑袋痛

    A题:水题,直接排序,判断第一个和最后一个之和和中间两个之和就可以了

    #include<stdio.h>
    #include<string.h>
    #include<iostream>
    #include<algorithm>
    #include<math.h>
    using namespace std;
    int n;
    int a[10];
    int main(){
        int cas=1;
        scanf("%d",&n);
        while(n--){
    
          for(int i=0;i<4;i++)
          scanf("%d",&a[i]);
           sort(a,a+4);
           if((a[0]+a[3])==(a[1]+a[2]))
           printf("Case %d: Yes
    ",cas++);
           else
               printf("Case %d: No
    ",cas++);
    
        }
    
        return 0;
    }

    C题:矩阵快速幂,,,,,给出的n其实就是让你求出s(n)的值,而S(N)的值就是你需要构造的矩形的边界长度,而n的范围比较大,所以需要用矩阵快速幂,这个很容易想到,用矩阵快速幂可以很快求出

    各个项。之后由于我们要的前n项之和摸m,fibonacci有一个简单的求和公式s(n)=2*f[n-1]+f[n-2]-1,所有我们就直接求出了矩形的长度,下面就是构造矩形,矩形的构造其实很容易发现边的长度

    为奇数的时候是构造不了的,因为总h会有一列一行相等,但是偶数的时候,我们可以对称构造,比如当n==4

    就可以对称

    1  1 1 -1

    1 1 -1 -1

    1 0 -1 -1

    0 -1 -1 -1

    直接暴力输出就可以了

    直接1A

    #include<iostream>
    #include<cstdlib>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    struct prog
    {
        int a[2][2] ;
        void init()
        {
            a[0][0]=a[1][0]=a[0][1]=1;
            a[1][1]=0;
        }
        void init1()
        {
            a[1][0]=a[0][1]=0;
            a[0][0]= a[1][1]=1;
        }
    };
    
    prog matrixmul ( prog a ,prog b , int m)
    {
        int i , j , k ;
        prog c ;
        for ( i = 0 ; i < 2; i ++ )
        {
            for ( j = 0 ; j < 2 ; j ++ )
            {
                c.a[i][j]=0;
                for ( k =0 ; k < 2; k ++ )
                    c.a[i][j]+=(a.a[i][k]*b.a[k][j]%m) ;
                c.a[i][j] %= m ;
            }
        }
        return c ;
    }
    prog mul (prog s , int k , int m)
    {
        prog ans ;
        ans.init1();
    
        while ( k >= 1 )
        {
            if ( k & 1 )
                ans = matrixmul ( ans , s , m) ;
            k = k >> 1 ;
            s = matrixmul ( s , s , m) ;
        }
        return ans ;
    }
    int ans[205][205];
    int main()
    {
        int n,  m, ca=1, t;
        scanf("%d", &t);
        while(t--)
        {
            scanf("%d%d", &n, &m);
            prog s ;
            s.init ( ) ;
            s = mul ( s , n-1 , m) ;
            int an=s.a[1][0], ann=s.a[0][0];
            int sn=(2*ann+an-1)%m;
            printf("Case %d: ", ca++);
            if(sn==0||sn%2==1)
            {
                printf("No
    ");
                continue;
            }
            if(sn%2==0)
            {
                for(int i=1;i<=sn;i++)
                {
                    for(int j=1;j<=(sn-i);j++)
                        ans[i][j]=1;
                }
                for(int i=1;i<=sn;i++)
                {
                    for(int j=sn;j>(sn-i+1);j--)
                        ans[i][j]=-1;
                }
                for(int i=1;i<=sn/2;i++)
                    ans[i][sn-i+1]=1;
                for(int i=sn/2+1;i<=sn;i++)
                    ans[i][sn-i+1]=0;
            }
            printf("Yes
    ");
            for(int i=1;i<=sn;i++)
            {
                for(int j=1;j<=sn;j++)
                {
                    if(j!=1) printf(" ");
                    printf("%d", ans[i][j]);
                }
                printf("
    ");
            }
        }
        return 0;
    }

    E题直接排序暴力比较就可以了

    #include<stdio.h>
    #include<string.h>
    #include<iostream>
    #include<algorithm>
    #include<math.h>
    using namespace std;
     int t;
     char str1[300],str2[300];
    int main(){
         scanf("%d",&t);
         int cas=1;
         while(t--){
            int n;
            scanf("%d",&n);
            getchar();
            for(int i=0;i<n;i++){
                char c;
                scanf("%c",&c);
                str1[i]=c;
                str2[i]=c;
            }
            getchar();
            sort(str2,str2+n);
            int cnt=0;
            for(int i=0;i<n;i++)
            if(str1[i]!=str2[i])
            cnt++;
            printf("Case %d: %d
    ",cas++,cnt);
         }
    }

    F题,还算比较坑,我和队友之前训练赛3,4次坑在了%I64D上面,这次又坑在了这上面,不知道是foj的事还是怎么了,别的oj没遇到过这种情况

    一开始我们想到的是使用树状数组,但是发现更新容易,查询费时间,,

    后来想到了线性的扫一遍,我们将数列重复一遍排成2*n的长度,方便循环的查询,vis数组被标记的时候代表以当前元素为开头的序列是有负数的,不会成立,我们从后往前从第一个负数开始扫,并累加,只要

    在扫到j的时候小于0,就说明以j元素开始的循环序列不成立,当大于0的时候,我们在找下一个负数,以此类推,被%I64d坑了好几次,尼玛

    最后n-vis数组中被标记的就可以了

    #include<stdio.h>
    #include<string.h>
    #include<iostream>
    #include<queue>
    #include<algorithm>
    #include<math.h>
    using namespace std;
    typedef long long int LL;
    LL a[2*500005];
    int vis[500005];
    int main()
    {
        int t;
        scanf("%d",&t);
        int ca=1;
        while(t--)
        {
            int n;
            scanf("%d", &n);
            memset(vis, 0, sizeof(vis));
            for(int i=0;i<n;i++)
            {
                scanf("%lld", &a[i]);
                a[i+n]=a[i];
            }
            int ans=0;
            for(int i=2*n-1;i>=n;i--)
            {
                if(i<n)
                    break;
                if(a[i]<=0)
                {
                    LL sum=0;
                    int j;
                    for(j=i;j>i-n;j--)
                    {
                        sum+=a[j];
                        if(sum<=0)
                        {
                            if(j>=n)
                                vis[j-n]=1;
                            else vis[j]=1;
                        }
                        else
                        {
                            break;
                        }
                    }
                    i=j;
                }if(i<n)
                    break;
            }
            for(int i=0;i<n;i++)
                if(vis[i]==1)
                    ans++;
            printf("Case %d: %d
    ", ca++, n-ans);
        }
    }

    k题,一个简单的递归,我们将n不断的分成k堆,而在回溯的时候我们希望比较的次数最大,,,,,,,n个物品平均分成k堆,我们假设k堆数都是在进行回溯排序好了之后的元素,那么着k堆n个物品进行的

    最大的比较次数就是(n-k)*(k-1)+(k-1)*k/2    ,这个公式我相信只要在纸上画一下一眼就看出来了,那么我们在dfs的时候,将他不断的分成k堆,并在回溯的时候将每一个小堆都按照上面的公式就行计算,累加就得出来了,

    -------------------------------------》下面的代码我们没有通过,我们赛后找了很久都没找到bug,以后想通了再回来纠正,不过思路是对的,我们赛后看别人的代码和我们的差不多,只是递归求和的顺序不一样

    import java.util.*;
    import java.math.*;
    public class qwerq 
    {
    
        public static void main(String args[])
        {
            int t;
            Scanner cin=new Scanner(System.in);
            t=cin.nextInt();
            for(int ca=1;ca<=t;ca++)
            {
                BigInteger n=cin.nextBigInteger(), m=cin.nextBigInteger();
                System.out.printf("Case %d: ", ca);
                System.out.println(abcd(n, m));
            }
        }
        public static BigInteger abcd(BigInteger a, BigInteger b)
        {
            BigInteger tttttt=new BigInteger("1"), ccccccc= new BigInteger("2");
            BigInteger num, div, ccc=new BigInteger("0");
            div=a.divide(b);
            num=a.remainder(b);
            if(div.compareTo(ccc)==0)
            {
                BigInteger aaa=num.subtract(tttttt), bbb=num.multiply(aaa), ans=bbb.divide(ccccccc);
                return ans;
            }
            BigInteger ans1, ans2;
            ans1=abcd(div, b);
            
            if(num.compareTo(ccc)==0)
                ans2=new BigInteger("0");
            else ans2=abcd(div.add(tttttt), b);
            
            ans1=ans1.multiply(b.subtract(num)); 
            ans2=ans2.multiply(num);
            
            BigInteger a1=a.subtract(b), a2=a1.multiply(b.subtract(tttttt)), a3=b.multiply(b.subtract(tttttt));
            a3=a3.divide(ccccccc);
            BigInteger ans0=a2.add(a3);
            return ans0.add(ans1.add(ans2));
        }
    }

    L题,就是非常水的bfs了,直接敲了就过了,

    我们只是需要讨论两种情况,如果没有0的话,我们只需要暴力数字的数量就可以了,要是有0的话,我们的bfs每一个含0的联通快的个数,之后加上没有被标记的数字的数量就可以了,

    #include<stdio.h>
    #include<string.h>
    #include<iostream>
    #include<queue>
    #include<algorithm>
    #include<math.h>
    using namespace std;
    int t;
    char str[15][15];
    bool vis[15][15];
    struct node
    {
        int x,y;
    };
    struct node1
    {
        int x1,y1;
    } que1[105];
    int n;
    int net[8][2]= {1,0,0,1,-1,0,0,-1,1,1,1,-1,-1,1,-1,-1};
    void bfs(int xx,int yy)
    {
        node u,v;
        u.x=xx,u.y=yy;
        queue<node>q;
        q.push(u);
        while(!q.empty())
        {
            u=q.front();
            q.pop();
            //bool flag1=false;
            for(int i=0; i<8; i++)
            {
                int tx=u.x+net[i][0];
                int ty=u.y+net[i][1];
                if((tx>=1&&tx<=n&&ty>=1&&ty<=n&&!vis[tx][ty])){
                if(str[tx][ty]=='0'){
                    v.x=tx;
                    v.y=ty;
                    q.push(v);
                }
                vis[tx][ty]=true;
                }
            }
    
        }
    }
    
    int main()
    {
        int t;
        scanf("%d",&t);
        int cas=1;
        while(t--)
        {
    
            bool flag=false;
            int sx,sy;
            sx=-1,sy=-1;
            int cnt=0;
            int ans=0;
            scanf("%d",&n);
            getchar();
            memset(vis,false,sizeof(vis));
            for(int i=1; i<=n; i++)
            {
                for(int j=1; j<=n; j++)
                {
                    scanf("%c",&str[i][j]);
                    if(str[i][j]=='0')
                    {
                        que1[cnt].x1=i;
                        que1[cnt].y1=j;
                        cnt++;
                        flag=true;
                    }
    
                }
                getchar();
            }
            if(!flag)
            {
                for(int i=1; i<=n; i++)
                {
    
                    for(int j=1; j<=n; j++)
                    {
                        if(str[i][j]!='@')
                        {
                            ans++;
                        }
                    }
    
                }
                printf("Case %d: %d
    ",cas++,ans);
    
            }
            else
            {
                for(int i=0; i<cnt; i++)
                {
                    int tx=que1[i].x1;
                    int ty=que1[i].y1;
                           if(!vis[tx][ty])
                    {
                        vis[tx][ty]=true;
                        bfs(tx,ty);
                        ans++;
                    }
    
                }
                for(int i=1; i<=n; i++)
                {
    
                    for(int j=1; j<=n; j++)
                    {
                        if(str[i][j]!='@'&&!vis[i][j])
                        {
                            ans++;
                        }
                    }
    
                }
                printf("Case %d: %d
    ",cas++,ans);
            }
    
        }
        return 0;
    }

    ******************************************************************************************************************************

    总的来说,今天最后一道java题没做出来真心很不爽,弱爆了---------------------------------------------------------------------------》》》》》》》》》》》》》》》》》

    ******************************************************************************************************************************

  • 相关阅读:
    spymemcache与spring结合
    Turtle库的学习积累
    汉诺塔绘图学习
    计算圆周率π和显示进度条
    川菜 in English
    一些必不可少的Sublime Text 2插件 钟磊的专栏 博客频道 CSDN.NET
    \usepackage{natbib}在latex模板写作中的心得_格致轩_百度空间
    Geant4新版本:新安装方法,新运行方式
    ubuntu系统备份
    Latex数学公式中的空格
  • 原文地址:https://www.cnblogs.com/13224ACMer/p/5402326.html
Copyright © 2011-2022 走看看