1. 程式人生 > >Codeforces Round #505 Div. 1 + Div. 2

Codeforces Round #505 Div. 1 + Div. 2

機會 lse bre names 最大 getchar() 就是 int main

傳送門:>Here<

從來沒打過\(CF\)(由於太晚了)…… 不知道開學了以後有沒有機會能夠熬夜打幾場,畢竟到現在為止都是\(unrated\)好尷尬啊~

今天早上打了幾題前幾天的比賽題……

A. \(Doggo \ Recoloring\)

此題應當是簽到題,但我還是傻了很久。很容易發現只要有任意一種狗的顏色超過\(1\),那麽這種狗就是可以變色的。那麽它永遠只需要變為任意一個與他相鄰的狗的顏色,數量不會減少反而增多。因此可以不停變下去。於是我們只需要統計一下是否有一種顏色是大於等於兩個的

代碼就不貼了

B. \(Weakened \ Common \ Divisor\)

題意為給出\(N\)

個整數對,要求找出任意一個數,能夠被任意一對中的其中一個數整除。稱為\(WCD\)

我的想法是先預處理出第一對的兩個數的所有因子,然後遍歷所有處理出來的因子,遍歷後面的每一對——如果當前因子合法就輸出。最後留下來的因子裏隨便取一個即可。\(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