1. 程式人生 > 其它 >總之就是 CF 1536 A & B

總之就是 CF 1536 A & B

前言

這是第二次打 CF ,體驗還不錯,爭取早日不做 Newbie (笑)。

這裡的題解大約都和洛谷上面對應題目我提交的題解基本一樣,就是多加了一些賽場描述。

添加了對應題目的 CF 和 洛谷連結,大家要是想做可以去切一切。

A Omkar and Bad Story

洛谷 | CF1536A CF | 1536A

這個題最一開始毫無思路,後來發現這題其實這道題挺水的。

題意簡述

問能否找到一個序列,這個序列中任意兩個數的差的絕對值都在這個序列中。

思路簡述

首先先來考慮哪些情況是不行的。

當這個序列中出現負數,這肯定是不行的,因為任意一個數減去負數都會得到一個更大的數。

因此當原序列中有負數的時候,我們得到的符合題意的序列是一個無限擴充套件的序列,而這顯然與題意不符。

然後,我們來考慮如何能夠構造出符合題意的序列。

實際上手模一下就能發現,當一個序列中的數是從 0 開始的連續正整數時,這個序列裡的任意兩個數字的差的絕對值都在這個序列中。

於是我們就先找到原序列的最大值,判斷完沒有負數之後,直接輸出 0 到這個最大值即可

Code

#include <bits/stdc++.h>
#define Heriko return
#define Deltana 0
#define Romano 1
#define S signed
#define U unsigned
#define LL long long
#define R register
#define I inline
#define D double
#define LD long double
#define mst(a, b) memset(a, b, sizeof(a))
#define ON std::ios::sync_with_stdio(false)
using namespace std;
I void fr(LL & x)
{
    LL f = 1;
    char c = getchar();
    x = 0;
    while (c < '0' || c > '9') 
    {
        if (c == '-') f = -1;
        c = getchar();
    }
    while (c >= '0' && c <= '9') 
    {
        x = (x << 3) + (x << 1) + c - '0';
        c = getchar();
    }
    x *= f;
}
I void fw(LL x)
{
    if(x<0) putchar('-'),x=-x;
    static LL stak[35];
    LL top=0;
    do
    {
        stak[top++]=x%10;
        x/=10;
    }
    while(x);
    while(top) putchar(stak[--top]+'0');
    putchar(' ');
}
S main()
{
    LL t;fr(t);
    while(t--)
    {
        LL n,a[105],amx=-1;
        bool d=false;
        fr(n);
        for(R LL i=1;i<=n;++i)
        {
            fr(a[i]);
            if(a[i]<0) d=true;
            if(a[i]>amx) amx=a[i];
        }
        if(d)
        {
            puts("NO");
            continue;
        }
        puts("YES");
        printf("%lld\n",amx+1);
        for(R LL i=0;i<=amx;++i) fw(i);
        putchar('\n');
    }
    Heriko Deltana;
}

後記

實際上這個題還告訴我們不要被樣例輸出迷惑了雙眼(笑),

還有就是 HYL 何老師上來直接秒了這題,這個思路基本就是何老師的。

看洛谷還有人直接輸出 0 到 100 ,確實離譜,但是正確性顯然。

B Prinzessin der Verurteilung

洛谷 | CF1536B CF | 1536B

這道題的題面......原神玩家直接狂喜。

大幻夢森羅永珍狂氣斷罪眼

切回正題,先來看題目是讓我們求什麼。

題意簡述

實際上這個題在洛谷的翻譯非常的簡潔明瞭了,不過我在 CodeForces 做的時候就理解不能

題目中定義了 MEX 是“在輸入中不作為連續子字串出現的最短字串”。

然後每組資料給你一個字串問你這個字串的 MEX 是什麼。

思路簡述

首先先來理解一下什麼是 MEX ,

當時我再看到這道題的時候是一臉懵的,因為這個翻譯出來確實很拗口。

於是我就在下面舉一個例子,裡面展現出來的東西,就是我個人的理解。希望不要假了QaQ

比如給你一個字串 abcax ,那麼這裡面所有連續子字串其實大家都會找:

"a" , "ab" , "abc" , "abca" , "abcax" , "b" , "bc" , "bca" , "bcax" , "c" , "ca" ......

由於全列出來就太多了,於是就列出這一些吧。

那麼 MEX 就是不在這裡面的定義上最小的字串,也就是字典序最小的。

可能看到這裡覺得這道題還有點難度?下面的一步直接讓這個題的難度消失。

我們來看資料範圍中說道:對於一個數據點中的所有資料 \(\sum n \ \le 1000\)

再由題目的定義可得 MEX 一定是原字串的字串,又因為 \(26^3 \ge 1000\) 所以 MEX 的長度不會大於 3 。

由此我就想到了一個比較暴力的類似桶的方法,

用一個 bool 陣列記錄這個字串有沒有出現過,最後按照順序輸出即可。

Code

這裡面有關初始化和最後迴圈的次序還是應當仔細想一下的

#include <bits/stdc++.h>
#define Heriko return
#define Deltana 0
#define Romano 1
#define S signed
#define U unsigned
#define LL long long
#define R register
#define I inline
#define D double
#define LD long double
#define mst(a, b) memset(a, b, sizeof(a))
#define ON std::ios::sync_with_stdio(false)
using namespace std;
I void fr(LL & x)
{
    LL f = 1;
    char c = getchar();
    x = 0;
    while (c < '0' || c > '9') 
    {
        if (c == '-') f = -1;
        c = getchar();
    }
    while (c >= '0' && c <= '9') 
    {
        x = (x << 3) + (x << 1) + c - '0';
        c = getchar();
    }
    x *= f;
}
I void fw(LL x)
{
    if(x<0) putchar('-'),x=-x;
    static LL stak[35];
    LL top=0;
    do
    {
        stak[top++]=x%10;
        x/=10;
    }
    while(x);
    while(top) putchar(stak[--top]+'0');
    putchar('\n');
}
char s[1005];
bool k[30][30][30];
S main()
{
    // freopen("my.in","r",stdin);
    LL t;fr(t);
    while(t--)
    {
        LL n;
        mst(k,0);
        fr(n);gets(s+1);
        for( LL i=1;i<=n;++i)
        {
            k[s[i]-'a'+1][0][0]=1;
            if(i>1) k[s[i]-'a'+1][s[i-1]-'a'+1][0]=k[s[i-1]-'a'+1][0][0]=1;
            if(i>2) k[s[i]-'a'+1][s[i-1]-'a'+1][s[i-2]-'a'+1]=k[s[i-1]-'a'+1][s[i-2]-'a'+1][0]=k[s[i-2]-'a'+1][0][0]=1;      
        }
        bool g=0;
        for( LL p=0;p<=26 and g==0;++p)
            for( LL j=min(p,1ll);j<=26 and g==0;++j)
                for( LL i=1;i<=26 and g==0;++i)
                    if(!k[i][j][p])
                    {
                        if(p) putchar(p+'a'-1);
                        if(j) putchar(j+'a'-1);
                        if(i) putchar(i+'a'-1);
                        putchar('\n');
                        g=1;
                    }
    }
    Heriko Deltana;
}

後記

這裡大約說明一下為什麼原神玩家狂喜(旅行者狂喜),幫你 Bing 好了