20180713练习赛 [AtCoder]ARC058-059 EASY

A - こだわり者いろはちゃん / Iroha’s Obsession AtCoder - 1973
B - いろはちゃんとマス目 / Iroha and a Grid AtCoder - 1974
C - いっしょ / Be Together AtCoder - 2019
D - アンバランス / Unbalanced AtCoder - 2020

        • A
        • B
        • C
        • D

A

水题
题意的话可以“样例分析法”

#include
#define MAXN 10005
int N,K,digit[6],ans;
bool d[15];
int main()
{
    scanf("%d %d",&N,&K);
    int x,len=0;
    for(int i=1;i<=K;i++)
    {
        scanf("%d",&x);
        d[x]=1;
    }
    for(int i=N;i<=10000005;i++)
    {
        bool f=0;
        x=i;
        while(x)
        {
            if(d[x%10])
            {
                f=1;
                break;
            }
            x/=10;
        }
        if(!f)
        {
            printf("%d\n",i);
            return 0;
        }
    }
    /*x=N;
    while(x)
    {
        len++;
        digit[len]=x%10;
        x/=10;
    }
    bool f=0;
    for(int i=1;i<=len;i++)
    {

    }*/
}

比较暴力(其实是很暴力),注意枚举的范围,应比MAXN大

B

非常好的一道题,很长,思维难度并不高,但是需要认真分析
Iroha and a Grid AtCoder - 1974【组合数学-乘法逆元-快速幂】【数学好题】

C

给出N个整数,把一个数变成另一个数的代价是(x-y)^2,求把这些数变成相同的数的最小代价。
刚开始的想法是把他们全部变成平均数(这可能就是直觉)
但是WA了(虽然样例能过)
然后就暴力枚举 范围也不大 个数和数的范围都才100
后来老师说他弄了一个什么很奇怪的函数,求了下导,然后算出来应该是在平均数的周围那3个数qwq

#include
#include
using namespace std;
#define MAXN 105
int N,ans=0x3f3f3f3f,cost;
int a[MAXN];
int Abs(int x)
{
    if(x<0) return -x;
    else return x;
}
int main()
{
    bool f=0;
    scanf("%d",&N);
    for(int i=1;i<=N;i++)
    {
        scanf("%d",&a[i]);
        if(i>1&&a[i]!=a[i-1]) f=1;
    }
    if(!f)
    {
        printf("0\n");
        return 0;
    }
    sort(a+1,a+N+1);
    for(int i=a[1];i<=a[N];i++)
    {
        cost=0;
        for(int j=1;j<=N;j++)
            cost+=Abs((a[j]-i)*(a[j]-i));
        if(costprintf("%d\n",ans);
    return 0;
}

D

我们称一个小写字母的序列是不平衡的当且仅当它的长度大于2,有一半的字母相同
给出一个字符串,找它的不平衡的子串
输出它的起始点和终止点的下标 如果没有,输出-1 -1

我这道题可壮观了
20180713练习赛 [AtCoder]ARC058-059 EASY_第1张图片

第一次的暴力做法TLE

#include
#include
using namespace std;
#define MAXN 100005
char s[MAXN];
int q[MAXN][30];
int main()
{
    scanf("%s",s+1);
    int len=strlen(s+1);
    for(int i=1;i<=len;i++)
    {
        memcpy(q[i],q[i-1],sizeof(q[i]));
        q[i][s[i]-'a']++;
    }
    for(int i=1;ifor(int j=i+1;j<=len;j++)
        {
            int tl=j-i+1;
            for(int k=i;k<=j;k++)
            {
                int x=q[j][s[k]-'a']-q[i-1][s[k]-'a'];
                if(x>tl/2)
                {
                    printf("%d %d\n",i,j);
                    return 0;
                }
            }
        }
    printf("-1 -1\n");
    return 0;
}

后来发现一个极其“优秀”的规律。
就是如果一个串存在不平衡的子串,那么它一定有一个长度为3的子串其中有两个字母是相同的(这个结论自己再琢磨琢磨,捯饬捯饬)
那反过来也是成立的,如果找不到一个长度为3的子串其中有两个字母是相同的,就说明没有解。(这个结论自己再琢磨琢磨,捯饬捯饬)
而且这题说随便出解,有SJ,那就线性查找有相邻的3个字母中有2个相同就输出结果。
若没有结果,就无解

#include
#include
using namespace std;
#define MAXN 100005
char s[MAXN];
int main()
{
    scanf("%s",s+1);
    int len=strlen(s+1);
    for(int i=1;i<=len-1;i++)
    {
        if(s[i]==s[i+2])
        {
            printf("%d %d\n",i,i+2);
            return 0;
        }
        if(s[i]==s[i+1])
        {
            printf("%d %d\n",i,i+1);
            return 0;
        }
    }
    printf("-1 -1\n");
    return 0;
}

上面那种写法看起来和

if(s[i]==s[i+1]||s[i]==s[i+2])

是等价的,但是考虑边界的时候却不一样,如果这么写,在len-1和len相等的时候就会输出len 到len+1,非法!!!

在写程序的时候,注意循环边界,递归边界及递推边界等情况

但是后来改了之后发现,第3个点最后一个和倒数第二个相同,输出len-1,len可以过,输出len-1,len就不行。
OJ有BUG???

你可能感兴趣的:(练习赛)