SICNU 2018 Summer Training #7

  打起来很累,感觉不是很好,但是题意都不是特别难懂

  Maratona de Programa¸c˜ao da SBC 2013

  首先是A题Zero or One,签到题

  给三个数(0或1),找不一样的是哪个,如果都一样就输出*

  

#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
    int a,b,c;
    cin>>a>>b>>c;
    if(a==b&&b==c) cout<<'*'<<endl;
    else if(a==b) cout<<'C'<<endl;
    else if(a==c) cout<<'B'<<endl;
    else if(b==c) cout<<'A'<<endl;
    return 0;
}

 D题Folding Machine感觉肯定很难,但是就是用莫名其妙,xjbg的方法水过去了

题意:给一串序列,问是否能够通过折叠转变成另一个序列

我的思路就是第二个序列的数可以用第一个序列的数表示就OK了,但是我只判断了第二个序列中的第一个数,就ac了。。

#include <cstdio>
#include <iostream>
#include <map>
#include <algorithm>
using namespace std;
    int cmp(int x,int y){
    return x>y;
    }
int main()
{
    int n,m;
    int sum1=0,sum2=0;
    int a[20],b[20];
    map<int,int>s;
    cin>>n;
    for(int i=0;i<n;i++){
        cin>>a[i];
        s[a[i]]++;
        sum1+=a[i];
    }
    sort(a,a+n,cmp);
    cin>>m;
    for(int i=0;i<m;i++){
        cin>>b[i];
        sum2+=b[i];
    }
    if(sum1==sum2){
        for(int i=0;i<n;i++){
            if(b[0]>=a[i]){
                if(s[a[i]]!=0){
                    b[0]-=a[i];
                    s[b[0]-a[i]];
                }
            }
        }
        if(b[0]==0) cout<<'S'<<endl;
        else cout<<'N'<<endl;
    }
    else cout<<'N'<<endl;
}

E题Dangerous Dive,也是道签到题,直接上代码吧

#include <cstdio>
#include <iostream>
#include <queue>
using namespace std;
int main()
{
    int n,m,t;
    int a[10005]={0};
    cin>>n>>m;
    for(int i=0;i<m;i++){
        cin>>t;
        a[t]=1;
    }
    if(n==m){
        cout<<'*'<<endl;
        return 0;
    }
    for(int i=1;i<=n;i++){
        if(a[i]==0) cout<<i<<' ';
    }
    return 0;
}

F题Triangles,是过的人超级多的,以为是道签到题,没想到没想到啊,wa了好多次还没写出来了,还有tle,后来经过大佬的提示可以通过前缀和降低复杂度。

题意是给圆上一些点,告诉每个点之间的弧长,,然后问可以构造多少个不同的等边三角形

 一开始想的比较简单,就是用一个两倍数组存,然后枚举起点,看能不能从这个点开始构造一个等边三角形,也就是能不能求和到总弧长的三分之一,然后发现tle了,后来发不需要枚举这么多点,因为像之前这么枚举的话,要重复算三倍的点,只需要枚举第一个等边三角形的两个点之间的点就OK了,发现又tle在之后的样例了,这个就很麻烦,最后在大佬的提示下,用前缀和降低复杂度,然后用map去存前缀和。。

#include <iostream>
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<queue>
#include<map>
using namespace std;
map<int,int>vis;
int main()
{
int n,m,a[100001]={0},j,temp=0,i,k,pre[100001]={0};
cin>>n;
int sum=0;
for(i=1;i<=n;i++)
{
    cin>>a[i];
    pre[i]=a[i]+pre[i-1];
    vis[pre[i]]++;
    sum+=a[i];
}
if(sum%3!=0)
    cout<<0<<endl;
else
{
    int ans=sum/3;
    int count=0,temp=0,cnt=0;
 for(i=1;i<=n;i++)
 {
         if(vis[ans+pre[i]]&&vis[ans*2+pre[i]]) cnt++;
}
 cout<<cnt<<endl;
}

return 0;
}

G题Lines of Containers,也是比较简单的吧

给一个n*m的矩阵,里面有1—n*m的数,问能否通过互换行或者列的方式让这个矩阵变成很舒服的矩阵,就是a【i】【j】=(i-1)*m+j

思路:就是把矩阵中1给找出来,记一下1的行和列,然后对1这一行(一列)进行排序,但是需要进行一些改变,就是在换序的时候是对这一列(行)进行换序,最后就只需要判断排序之后的这个矩阵能不能变成题目要求的这样。

#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
    int num[305][305];
    int n,m;
    int a=0,b=0;
    int sum=0;
    cin>>n>>m;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            cin>>num[i][j];
            if(num[i][j]==1){
                a=i;
                b=j;
            }
        }
    }
    for(int i=1;i<=m;i++){
        if(num[a][i]!=i){
            int flag=0;
            for(int j=i+1;j<=m;j++){
                if(num[a][j]==i){
                    if(i==1) b=j;
                    sum++;
                    flag=1;
                    for(int t=1;t<=n;t++){
                          swap(num[t][j],num[t][i]);
                    }
                }
            }
            if(flag==0){
                cout<<'*'<<endl;
                return 0;
            }
        }
    }
    for(int i=1;i<=n;i++){
        if(num[i][b]!=(i-1)*m+b){
            int flag=0;
            for(int j=i+1;j<=n;j++){
                if(num[j][b]==(i-1)*m+b){
                    sum++;
                    flag=1;
                    for(int t=1;t<=m;t++){
                          swap(num[j][t],num[i][t]);
                    }
                }
            }
             if(flag==0){
                cout<<'*'<<endl;
                return 0;
            }
        }
    }
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            if(num[i][j]!=((i-1)*m+j)){
                cout<<'*'<<endl;
                return 0;
            }
        }
    }
    cout<<sum<<endl;
    return 0;
}

还有就是C题,题很长,题意也比较难懂,所以在比赛中就没有去碰。

后面队友在补题的时候,说可以用dfs和拓扑排序去做。想了想贼有道理

题意就是,先给一些上下级的关系,然后构成一张关系图,然后会给你一些修改和查询,如果是修改的话就是交换两个人的位置,如果是查询的话,就是查询要查询的人的上级(包括直接和间接)中年龄最小的,如果比自己小,就输出这个年龄,如果没有即输出*

思路就是DFS,但是在修改的时候用数组进行维护,就是基本的关系网不变,但是在每次修改的时候,将位置修改的放入数组中,如果查询到这个人的时候判断一下,如果修改过,就到修改的这个人的位置上再进行dfs

 

posted @ 2018-08-08 10:45  maybe96  阅读(175)  评论(0编辑  收藏  举报