训练赛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题没做出来真心很不爽,弱爆了---------------------------------------------------------------------------》》》》》》》》》》》》》》》》》

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

原文地址:https://www.cnblogs.com/13224ACMer/p/5402326.html