Codeforces Round #505 Div. 1 + Div. 2
傳送門:>Here<
從來沒打過\(CF\)(由於太晚了)…… 不知道開學了以後有沒有機會能夠熬夜打幾場,畢竟到現在為止都是\(unrated\)好尷尬啊~
今天早上打了幾題前幾天的比賽題……
A. \(Doggo \ Recoloring\)
此題應當是簽到題,但我還是傻了很久。很容易發現只要有任意一種狗的顏色超過\(1\),那麽這種狗就是可以變色的。那麽它永遠只需要變為任意一個與他相鄰的狗的顏色,數量不會減少反而增多。因此可以不停變下去。於是我們只需要統計一下是否有一種顏色是大於等於兩個的
代碼就不貼了
B. \(Weakened \ Common \ Divisor\)
題意為給出\(N\)
我的想法是先預處理出第一對的兩個數的所有因子,然後遍歷所有處理出來的因子,遍歷後面的每一對——如果當前因子合法就輸出。最後留下來的因子裏隨便取一個即可。\(T\)了第\(45\)個點……
事實上慢就慢在我們不能夠處理因子,而是應當處理素因子。因為如果一個非素數\(x\)能夠作為\(WCD\),那麽\(x\)的所有素因子肯定都可以滿足。
/*By DennyQi 2018*/ #include <cstdio> #include <queue> #include <cstring> #include <algorithm> #include <cmath> #define r read() using namespace std; typedef long long ll; const int MAXN = 10010; const int MAXM = 20010; const int INF = 1061109567; inline int Max(const int a, const int b){ return (a > b) ? a : b; } inline int Min(const int a, const int b){ return (a < b) ? a : b; } inline int read(){ int x = 0; int w = 1; register char c = getchar(); for(; c ^ '-' && (c < '0' || c > '9'); c = getchar()); if(c == '-') w = -1, c = getchar(); for(; c >= '0' && c <= '9'; c = getchar()) x = (x<<3) + (x<<1) + c - '0'; return x * w; } int N,lim,t1; ll f[200010],a[200010],b[200010]; inline void Fenjie(ll a){ for(ll i = 2; i * i <= a; ++i){ if(a % i == 0){ f[++t1] = i; while(a % i == 0){ a /= i; } } } if(a > 1){ f[++t1] = a; } } int main(){ N = r; for(int i = 1; i <= N; ++i){ a[i] = r, b[i] =r ; } Fenjie(a[1]); Fenjie(b[1]); bool flg = 0; for(int i = 1; i <= t1; ++i){ flg = 0; for(int j = 2; j <= N; ++j){ if((a[j]%f[i] != 0) && (b[j]%f[i] != 0)){ flg = 1; break; } } if(!flg){ printf("%lld", f[i]); return 0; } } printf("-1"); return 0; }
C. \(Plasticine \ zebra\)
給出一個字符串,每個字符不是\(b\)就是\(w\)。每一次操作可以選擇一個斷點,然後讓斷點兩邊的全部翻轉。無論操作幾次。定義一個斑馬串,其相鄰元素不重復、問最大的斑馬串是多長?也就是要通過若幹次操作找到最長的\(bwbwbw..\)或\(wbwbwb...\)
找到一個斷點然後兩邊都翻轉實際上是可以等價的。例如一個字符串\(abcdefgh\),在\(c\)後面斷了,那麽就變為\(abc \ | \ defgh\),翻轉後得到\(cbahgfed\)。我們發現其等價於\(abc\)放到\(defgh\)後面,然後整個翻轉。而如果我們找到了一個斑馬串,其翻過來依然是斑馬串。因此我們只需要把字符串本身復制一遍接在後面,然後在這個兩倍的字符串中找到最長的斑馬串。(長度不能超過\(N\)
為什麽這樣就好了呢?依然距離,將\(abcdefg\)復制一遍得到\(abcdefgabcdefg\)。任取一段長度為\(N\)的連續的子序列,其頭尾相當於斷點。因此這就相當於枚舉了斷點了
/*By DennyQi 2018*/
#include <cstdio>
#include <queue>
#include <cstring>
#include <algorithm>
#define r read()
using namespace std;
typedef long long ll;
const int MAXN = 10010;
const int MAXM = 20010;
const int INF = 1061109567;
inline int Max(const int a, const int b){ return (a > b) ? a : b; }
inline int Min(const int a, const int b){ return (a < b) ? a : b; }
inline int read(){
int x = 0; int w = 1; register char c = getchar();
for(; c ^ '-' && (c < '0' || c > '9'); c = getchar());
if(c == '-') w = -1, c = getchar();
for(; c >= '0' && c <= '9'; c = getchar()) x = (x<<3) + (x<<1) + c - '0'; return x * w;
}
int N,ans;
char s[200010];
int f[200010];
int main(){
scanf("%s", s);
N = strlen(s);
for(int i = N; i < 2 * N; ++i) s[i] = s[i-N];
for(int i = 0; i < 2 * N; ++i){
if(i - 1 >= 0){
if(s[i] != s[i-1]){
f[i] = f[i-1] + 1;
}
else{
f[i] = 1;
}
}
else{
f[i] = 1;
}
if(f[i] <= N){
ans = Max(ans, f[i]);
}
}
printf("%d", ans);
return 0;
}
另外的幾道題暫時還沒做,有時間再更吧……
Codeforces Round #505 Div. 1 + Div. 2