【CF】Codeforces Round #505 (Div. 1 + Div. 2)
終於上紫啦!
撒花!
刺激,一回二高就打CF,還好準備時間充裕,下了Firefox,調好Dev-C++,裝了CF-Predictor。(廣告預警)
強烈推薦外掛 CF-Predictor !讓你實時瞭解預計Rating Change,從而面向Rating做題(逃
各大瀏覽器外掛中心、Tampermonkey、搜尋CF-Predictor,一分錢不要,白白帶回家!
---以上是廣告時間---
下面是正題:HackCodeforces Round #505題解。
題解
A. Doggo Recoloring
題意:給你一個字串,每次操作你可以選擇一個出現過兩次或以上的字元,把它們全部變成你指定的另一個字元,你可以進行無限次操作,問你能否使得這個字串只含一種字元。
題解:很容易發現,如果這個字串中含有一個字元,它出現過兩次或以上,那麼你只需要把這幾個字元變成另一種在這個字串中出現過的字元,然後不停重複以上操作,最後得到的字串就一定只含有一種字元了。
證明是顯然的:若你能進行上述操作,那麼答案一定是Yes,否則這個字串不能進行任何操作,答案就是No(伏筆)。
所以就統計有沒有一個字元出現過兩次或以上。
快速碼完了交上去,螢幕上顯示著In queue,突然想到,n=1
咋沒有撤回提交功能啊。。。。。。o(╥﹏╥)o
還是怪自己不細心,Wrong answer on pretest 4,-50pts。
證明是顯然的:若你能進行上述操作,那麼答案一定是Yes,否則這個字串不能進行任何操作,答案就是No。n=1除外!!!!!一定是Yes!!!!!
Pretests passed,下一題。
B. Weakened Common Divisor
題意:給你n對數,讓你找一個大於1的數x,滿足x是每對數中其中一個的因子。
題解:一讀懂題,開始瞎猜。
lc:把每對數求lcm,把求完lcm的n個數求gcd不就是答案嗎。
於是大家一起瘋狂碼,lc:我WA了。
仔細一想,錯的!
。。。。。。
一看時間:00:18:10
別卡B題啊(伏筆)。
老實(naive)的我思考了一下,能不能把這個做法改一下,20分鐘後想到一種做法:把用上面的方法求得的答案取質因子。
正確性容易證明。
00:41:50 Pretests passed [pretests]
咋花了41分鐘(伏筆)才做出B啊。。。。涼透。。。。
突然一想,複雜度對嗎?
然後往程式裡一輸入:
2
998244353 1000000007
998244353 1000000007
TLE!
求質因子極限要,然後兩個大質數一乘再開根,Boom!
Pretests:
這Pretest有何用!!!
做法推翻。。。涼透。。。
lc:不對,你把第一對數的兩個數都分解質因子,然後每個質因子暴力判就完了啊。
我怕是腦子抽了。
lc:00:45:53 Pretests passed [main tests]
然而我各種WA
01:10:09 Pretests passed [main tests]
咋01:10:09才過B啊。。。。。
一看分數:370
比A還少。。。。。
一定有人寫我之前的做法的,果斷鎖。
C. Plasticine zebra
題意:給你一個01串,你可以把這個字串從任何位置切開,兩邊各自翻轉,拼回來。可以進行無限多次。求你經過這些操作後能得到的字串中01相間子串的最長長度。
題解:就在碼B題的時候(就是lc過了B我還在各種WA的時候)
lc(就在我正後方一米):啊~~~~~我C過了!!!!!!!!!!!!!!
lc:就是你把這個串倍長,然後求它的最長01相間子串長度就可以了。
你也先等我過了B啊,大佬。
然後看到lc的status:
01:00:46 Pretests passed [pretests]
01:02:29 Hacked by cubercsl
同時lc:等等我C被hack了!
謝謝,我放心碼B題了,大佬。
lc:哦答案要與原串長度取min。我再交。
然後等了很久,沒有被hack。
應該是正解了。。。我剛好過了B,於是碼完C,Pretests passed。
我:真的是正解嗎,你要不要鎖一下看看別人怎麼寫。
lc:你鎖吧。
我:(狠心)反正我B鎖了,那我把C也鎖了吧!(切勿模仿,幸好沒有伏筆)
好像真的這樣做啊。
回宿舍的路上想到的粗略證明:把這個串進行操作後一定是倍長串的子串。
下面進入 Hackforces 講故事時間:
看D題,暫時沒有思路。
翻翻別人B題的程式碼,前幾個看來很正經,突然看到一個,怎麼這麼熟悉???
for(ll i=2;i*i<=ans;++i)
{
if(ans%i==0)
{
cout<<i;
return 0;
}
}
cout<<ans;
這不就是我之前的做法嗎!
點下hack it!,輸入那組資料:
2
998244353 1000000007
998244353 1000000007
來不及猶豫了! 按下Hack按鈕
In queue...
心跳加速中...
狀態up!八分鐘後
這時候有個人來hack我的B題,然而他並沒有成功。我一看他的程式碼結尾,熟悉的for迴圈!
這個Room的B題貌似就沒有用那種做法的了,於是看看Locked的C題。原本沒抱太多希望,因為我們Room早有人把C題鎖了,讓我聯想到lc房的那位大佬,一看到有人沒取min就光速hack掉,於是我便以為我們Room鎖了C的人也把沒取min的hack了。
然而事實是這樣的:
這個人答案沒取min!
這個人程式碼好醜,但是答案沒取min!
這個人答案也沒取min!
然而這時候,CF-Predictor告訴我,我還是會掉Rating的(伏筆)!
那死也要把D題暴力打出來,FST就FST!
D. Recovering BST
題意:給你n個數,讓你判斷,是否用這些陣列成一棵二叉搜尋樹,使得每條邊上的兩個數的gcd不為1。
題解:不會啊。我只會打暴力,正解是的dp啊。
場上寫了個的暴搜,過了Pretest。
還把System test過了!!!
也許複雜度是對的
好吧其實原因可能是用了bitset壓位,常數極小。
程式碼
A
#include <bits/stdc++.h>
using namespace std;
int cnt[30];
int main()
{
int n;
string s;
cin >> n >> s;
for(int i=0;i<s.length();++i)++cnt[s[i]-'a'];
for(int i=0;i<26;++i)if(cnt[i]>=2){puts("Yes");return 0;}
if(n==1)puts("Yes");
else puts("No");
}
B
#include <bits/stdc++.h>
using namespace std;
int s[10000001],isp[10000001];
bool flag[10000001];
int main()
{
int n,a,b;
scanf("%d",&n);
scanf("%d%d",&a,&b);
if(n==1){if(a==1)printf("%d\n",b==1?-1:b);else printf("%d\n",a);return 0;}
for(register int i=2;i<=45000;++i)
{
bool check=true;
for(register int j=2;j<=sqrt(i);++j)
if(i%j==0)
{
check=false;
break;
}
isp[i]=check;
}
for(int i=2;i<=sqrt(a);++i)
{
if(a%i==0 && isp[i])s[++s[0]]=i;
while(a%i==0)a/=i;
}
if(a>1)
s[++s[0]]=a;
for(int i=2;i<=sqrt(b);++i)
{
if(b%i==0 && isp[i])s[++s[0]]=i;
while(b%i==0)b/=i;
}
if(b>1)
s[++s[0]]=b;
memset(flag,true,sizeof(flag));
for(int i=2;i<=n;++i)
{
int a,b;
scanf("%d%d",&a,&b);
for(int j=1;j<=s[0];++j)
{
if(a%s[j]!=0 && b%s[j]!=0)flag[j]=false;
}
}
int ans=-1;
for(int i=1;i<=s[0];++i)if(flag[i])ans=s[i];
printf("%d\n",ans);
}
C
#include <bits/stdc++.h>
using namespace std;
int main()
{
string s;
cin >> s;
string t=s;
s+=t;
int ans=1,now=1;
for(int i=1;i<s.length();++i)
{
if(s[i]==s[i-1])now=1;
else ++now;
ans=max(ans,now);
}
cout << min((int)t.length(),ans);
}
D
#include<bits/stdc++.h>
using namespace std;
int n,a[701];
bitset<701> vis2[701][701],ans[701][701];
bool ok[701][701];
int check(int l,int r,int root)
{
if(r<l)return true;
if(l==r)return ok[l][root];
if(vis2[l][r][root])return ans[l][r][root];
for(int i=l;i<=r;++i)
if(ok[i][root] && check(l,i-1,i) && check(i+1,r,i))
{
vis2[l][r][root]=1;
ans[l][r][root]=1;
return true;
}
vis2[l][r][root]=2;
return false;
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;++i)
scanf("%d",a+i);
for(int i=1;i<=n;++i)
{
for(int j=1;j<=n;++j)
ok[i][j]=__gcd(a[i],a[j])!=1;
ok[0][i]=true;
ok[i][0]=true;
}
if(check(1,n,0))puts("Yes");else puts("No");
}
比賽結束後大半部分的人都FST了,其實不做D也能漲的。
下一場Codeforces,Div.1見!