SDUT 2020 Summer Team Contest ---2 题解+反思

题目链接
A - Alex Origami Squares
水题
题意:给定一个长方形,在长方形内部画三个相同的正方形,问正方形的边长最大是多大。

题解:根据长宽比例可以算出三种情况,如果长比宽大三倍以上,那么正方形边长就是宽;如果长在宽的1.5倍到3倍之间,那么正方形边长就是长/3;如果长在宽的1到1.5倍之间,那么就看做是在长方形内部画一个田字,正方形边长就是宽/2

#include <bits/stdc++.h>
#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;
int main()
{
    freopen("alex.in","r",stdin);
    freopen("alex.out","w",stdout);
    int n,m;
    while(cin>>n>>m)
    {
        double ans;
        if(n<m)
            swap(n,m);
        if(n>=3.0*m)
            ans=m*1.0;
        else if(n>=3.0*m/2.0)
            ans=n*1.0/3.0;
        else
            ans=m*1.0/2.0;
        printf("%.6f\n",ans);
    }
    return 0;
}

B - Black and White
题意:给定X,Y,分别表示由’.‘和’@'组成的连通块的个数。

思路:假如X<Y,我们用两部分来构造这个结果,第一部分由一个’.‘连通块和Y-(X-1)割’@‘连通块组成,第二个部分由X-1个’.‘连通块和X-1个’@'连通块组成.

#include<bits/stdc++.h>
using namespace std;
const int maxn=10010;
char s[1111][111];
int main()
{
    freopen("black.in","r",stdin);
    freopen("black.out","w",stdout);
    int r,c;
    cin>>r>>c;
    r--;
    c--;
    int i,j;
    for(i=0; i<500; i++)
    {
        for(j=0; j<100; j++)
        {
            s[i][j]='@';
        }
    }
    for(i=500; i<1000; i++)
    {
        for(j=0; j<=100; j++)
        {
            s[i][j]='.';
        }
    }
    for(i=0; i<500; i+=2)
    {
        for(j=0; j<100; j+=2)
        {
            if(!c)
                break;
            s[i][j]='.';
            c--;
        }
        if(!c)
            break;
    }
    for(i=501; i<1000; i+=2)
    {
        for(j=0; j<100; j+=2)
        {
            if(!r)
                break;
            s[i][j]='@';
            r--;
        }
        if(!r)
            break;
    }
    printf("1000 100\n");
    for(i=0; i<1000; i++)
    {
        for(j=0; j<100; j++)
        {
            printf("%c",s[i][j]);
        }
        printf("\n");
    }
    return 0;
}

C - Concatenation
题意:
AA中取出一个前缀,BB中取出一个后缀,问问拼出多少个字符串

思路:
感觉很巧妙的一道题。
首先能构造出的字符串总数为 lena∗lenblena∗lenb。
那么假设从AA中取出的前缀结尾字符为xx,那么从BB中取出的后缀首字符为xx的有mm个,那么将AA的结尾去掉或者将BB的首部去掉,拼成的字符串是一样的,也就是重复算了mm次。

假设AA中结尾为字符xx的有nn个,那么对于字符xx来说,一共多算了n∗mn∗m次。
所以统计出AA中前缀结尾字符出现次数和BB中所有后缀开头字符出现次数,减去所有相同字符个数乘积。

但是注意A串第一个字符和B串最后一个字符不统计,因为首字符往前和尾字符往后是空的,发生不了重复。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<bits/stdc++.h>
using namespace std;
char a[100100],b[100100];
long long int x,y,z,i,j,c[26],d[26],m,n;
int main()
{
    freopen("concatenation.in","r",stdin);
    freopen("concatenation.out","w",stdout);
    scanf("%s%s",a,b);
    x=strlen(a);
    y=strlen(b);
    m=x*y;
    for(z=1; z<x; z++)
        c[a[z]-'a']++;
    for(z=0; z<y-1; z++)
        d[b[z]-'a']++;
    for(z=0; z<26; z++)
    {
        if(c[z]!=0&&d[z]!=0)
            m-=c[z]*d[z];
    }
    printf("%lld\n",m);
    return 0;
}

E - Easy Arithmetic
题意:给定一个长度不超过1000的字符串表达式,向该表达式中加入’+‘或’-’,使得表达式的值最大,输出该表达式。

题解:比如300-456就改成300-4+56,遇到二位数以上的减数的情况就变成-首位+剩下的,这样会使得表达式值最大。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<bits/stdc++.h>
using namespace std;
char s[10000];
int x,y,z,i,j,m,n;
int main()
{
    freopen("easy.in","r",stdin);
   freopen("easy.out","w",stdout);
    scanf("%s",s);
    while(s[z]!='\0')
    {
        if(s[z]=='-')
        {
            z++;
            printf("-%c",s[z]);
            z++;
            while(s[z]=='0')
            {
                printf("+0");
                z++;
            }
            if(s[z]>='0'&&s[z]<='9')
            {
                printf("+");
                while(s[z]>='0'&&s[z]<='9')
            {
                printf("%c",s[z]);
                z++;
            }
            }
        }
        else
        {
            printf("%c",s[z]);
            z++;
        }
    }
    return 0;
}

H - Hash Code Hacker
由于s[i]⋅31n−1−i+s[i+1]⋅31n−2−i=(s[i]+1)⋅31n−1−i+(s[i+1]−31)⋅31n−2−i ,故只要第i位不是′z′和′Z′,且第i+1位是一个不是′z′的小写字母,那么第i位加一,第i+1位变为这个小写字母对应的大写字母再加一即得到两个hash值相同的不同字符串,初始给1000个位置全部赋为′a′,每次对于不同的i进行上述操作即可得到至多1000个hash值相同的字符串

#include<iostream>
#include<cstdio>
#include<cstring>
#include<bits/stdc++.h>
using namespace std;

int main()
{
    freopen("hash.in","r",stdin);
    freopen("hash.out","w",stdout);
    int n;
    cin>>n;
    int i,j;
    for(i=1; i<=n; i++)
    {
        for(j=1; j<=1000; j++)
        {
            if(i==j+1&&i!=1)
                printf("%c",'G' - 1);
            else if(i==j&&i!=1)
                printf("%c",'G' + 31);
            else
                printf("G");
        }
        printf("\n");
    }
    return 0;
}

L - Lucky Chances
水题
规模很小,暴力判即可

#include<iostream>
#include<cstdio>
#include<cstring>
#include<bits/stdc++.h>
using namespace std;
int a[105][108];
int x,y,z,i,j,m,n,sum;
int main()
{
    freopen("lucky.in","r",stdin);
    freopen("lucky.out","w",stdout);
    scanf("%d %d",&x,&y);
    for(i=1; i<=x; i++)
        for(j=1; j<=y; j++)
            scanf("%d",&a[i][j]);
    for(i=1; i<=x; i++)
        for(j=1; j<=y; j++)
        {
            for(m=i-1; m>=1; m--)
                if(a[m][j]>=a[i][j])break;
            if(m==0)sum++;
            for(m=i+1; m<=x; m++)
                if(a[m][j]>=a[i][j])break;
            if(m==x+1)sum++;
            for(m=j-1; m>=1; m--)
                if(a[i][m]>=a[i][j])break;
            if(m==0)sum++;
            for(m=j+1; m<=y; m++)
                if(a[i][m]>=a[i][j])break;
            if(m==y+1)sum++;
        }
    cout<<sum;
    return 0;
}

反思:
1.第一题虽然是水题,但是没有注意到需要文件的输入输出,导致wa了好多遍,以后需要多加注意
2.题目中有样例只是进行辅助理解题意的作用,并没有最后输出的格式,不能想当然
3.算法技巧掌握的还是太少,要继续学习

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值