總之就是 CF 1536 A & B
前言
這是第二次打 CF ,體驗還不錯,爭取早日不做 Newbie (笑)。
這裡的題解大約都和洛谷上面對應題目我提交的題解基本一樣,就是多加了一些賽場描述。
添加了對應題目的 CF 和 洛谷連結,大家要是想做可以去切一切。
A Omkar and Bad Story
這個題最一開始毫無思路,後來發現這題其實這道題挺水的。
題意簡述
問能否找到一個序列,這個序列中任意兩個數的差的絕對值都在這個序列中。
思路簡述
首先先來考慮哪些情況是不行的。
當這個序列中出現負數,這肯定是不行的,因為任意一個數減去負數都會得到一個更大的數。
因此當原序列中有負數的時候,我們得到的符合題意的序列是一個無限擴充套件的序列,而這顯然與題意不符。
然後,我們來考慮如何能夠構造出符合題意的序列。
實際上手模一下就能發現,當一個序列中的數是從 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
這道題的題面......原神玩家直接狂喜。
大幻夢森羅永珍狂氣斷罪眼
切回正題,先來看題目是讓我們求什麼。
題意簡述
實際上這個題在洛谷的翻譯非常的簡潔明瞭了,不過我在 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 好了。