【AtCoder】CADDi 2018

C - Product and GCD

題解

直接分解質因數,而後gcd每次多一個質因數均攤到每一個\(N\)上的個數c++

代碼

#include <bits/stdc++.h>
#define fi first
#define se second
#define pii pair<int,int>
#define mp make_pair
#define pb push_back
#define enter putchar('\n')
#define space putchar(' ')
#define eps 1e-8
#define mo 974711
#define MAXN 200005
//#define ivorysi
using namespace std;
typedef long long int64;
typedef double db;
template<class T>
void read(T &res) {
    res = 0;char c = getchar();T f = 1;
    while(c < '0' || c > '9') {
    if(c == '-') f = -1;
    c = getchar();
    }
    while(c >= '0' && c <= '9') {
    res = res * 10 + c - '0';
    c = getchar();
    }
    res *= f;
}
template<class T>
void out(T x) {
    if(x < 0) {x = -x;putchar('-');}
    if(x >= 10) {
    out(x / 10);
    }
    putchar('0' + x % 10);
}
int64 N,P;
int64 g = 1;
int main() {
#ifdef ivorysi
    freopen("f1.in","r",stdin);
#endif
    read(N);read(P);
    if(N == 1) {out(P);enter;return 0;}
    for(int64 i = 2 ; i <= P / i ; ++i) {
        if(P % i == 0) {
            int64 cnt = 0;
            while(P % i == 0) {P /= i;++cnt;}
            int64 k = cnt / N;
            while(k--) g *= i;
        }
    }
    out(g);enter;
    return 0;
}

D - Harlequin

題解

這題簡直了,比賽完兩分鐘就想出來,比賽時候硬是怎麼也想不出來ui

若是全是偶數確定後手必勝,由於先手在哪一個堆拿一個後手在這個堆跟一個
若是某個堆是奇數先手能夠把局面轉變爲全是偶數而後本身當後手spa

因此有奇數先手必勝
全是偶數後手必勝code

#include <bits/stdc++.h>
#define fi first
#define se second
#define pii pair<int,int>
#define mp make_pair
#define pb push_back
#define enter putchar('\n')
#define space putchar(' ')
#define eps 1e-8
#define mo 974711
#define MAXN 200005
//#define ivorysi
using namespace std;
typedef long long int64;
typedef double db;
template<class T>
void read(T &res) {
    res = 0;char c = getchar();T f = 1;
    while(c < '0' || c > '9') {
    if(c == '-') f = -1;
    c = getchar();
    }
    while(c >= '0' && c <= '9') {
    res = res * 10 + c - '0';
    c = getchar();
    }
    res *= f;
}
template<class T>
void out(T x) {
    if(x < 0) {x = -x;putchar('-');}
    if(x >= 10) {
    out(x / 10);
    }
    putchar('0' + x % 10);
}
int N;
int a[MAXN],cnt[2];
int main() {
#ifdef ivorysi
    freopen("f1.in","r",stdin);
#endif
    read(N);
    for(int i = 1 ; i <= N ; ++i) read(a[i]);
    for(int i = 1 ; i <= N ; ++i) {
        if(a[i] & 1) {puts("first");return 0;}
    }
    puts("second");
    return 0;
}

E - Negative Doubling

題解

有點麻煩的一道題,想起來容易寫起來不容易
就是我對於每一個序列確定是要求不斷乘4使得序列不降,正着反着都要算
就說從\(1-N\)不降
咱們從後往前加數
若是加的這個數比它的後一個小,那麼\(dp[i] = dp[i + 1]\)
不然後一個數確定會變大,後一個數變大會引發以後的一些值變大,若是和後面相連且已經增長過的位置都會同時加上這個數,同時這個增長了還會使後面沒有增長過的位置增長
這個能夠用鏈表維護,由於每一個點被增長後就被刪除了,因此鏈表維護每次暴力更新就好get

代碼

#include <bits/stdc++.h>
#define fi first
#define se second
#define pii pair<int,int>
#define mp make_pair
#define pb push_back
#define enter putchar('\n')
#define space putchar(' ')
#define eps 1e-8
#define mo 974711
#define MAXN 200005
//#define ivorysi
using namespace std;
typedef long long int64;
typedef double db;
template<class T>
void read(T &res) {
    res = 0;char c = getchar();T f = 1;
    while(c < '0' || c > '9') {
    if(c == '-') f = -1;
    c = getchar();
    }
    while(c >= '0' && c <= '9') {
    res = res * 10 + c - '0';
    c = getchar();
    }
    res *= f;
}
template<class T>
void out(T x) {
    if(x < 0) {x = -x;putchar('-');}
    if(x >= 10) {
    out(x / 10);
    }
    putchar('0' + x % 10);
}
int N,val[MAXN],pre[MAXN],suf[MAXN];
int64 a[MAXN],dp[2][MAXN],ans;
void Init() {
    read(N);
    for(int i = 1 ; i <= N ; ++i) read(a[i]);
}
void Solve() {
    suf[0] = 1;
    for(int i = 1 ; i <= N ; ++i) suf[i] = i + 1,pre[i] = i - 1;
    pre[N + 1] = N;
    for(int i = N ; i > 1 ; --i) {
        if(a[i] >= a[i - 1]) {
            int64 t = a[i];
            while(t / 4 >= a[i - 1]) {val[i] -= 2; t /= 4;}
        }
        else {
            int64 t = a[i];
            while(t < a[i - 1]) {val[i] += 2; t *= 4;}
        }
    }
    for(int i = N - 1 ; i >= 1 ; --i) {
        dp[0][i] = dp[0][i + 1];
        if(a[i] > a[i + 1]) {
            int t = val[i + 1],p = i + 1;
            while(1) {
                dp[0][i] += 1LL * t * (suf[p] - p);
                if(suf[p] - 1 != p) val[suf[p] - 1] += t;
                if(val[suf[p] - 1] + val[suf[p]] <= 0) break;
                if(suf[p] == N + 1) break;
                t = val[suf[p] - 1] + val[suf[p]];
                p = suf[p];val[p] = t;
                pre[suf[p]] = pre[p];suf[pre[p]] = suf[p];
            }
            pre[suf[i + 1]] = pre[i + 1];
            suf[pre[i + 1]] = suf[i + 1];
        }
    }
    suf[0] = 1;
    for(int i = 1 ; i <= N ; ++i) pre[i] = i - 1,suf[i] = i + 1;
    pre[N + 1] = N;
    memset(val,0,sizeof(val));
    for(int i = 1 ; i < N ; ++i) {
        if(a[i] < a[i + 1]) {
            int64 t = a[i];
            while(t < a[i + 1]) {t *= 4;val[i] += 2;}
        }
        else {
            int64 t = a[i];
            while(t / 4 >= a[i + 1]) {t /= 4;val[i] -= 2;}
        }
    }
    for(int i = 2 ; i <= N ; ++i) {
        dp[1][i] = dp[1][i - 1];
        if(a[i] > a[i - 1]) {
            int t = val[i - 1],p = i - 1;
            while(1) {
                dp[1][i] += 1LL * t * (p - pre[p]);
                if(pre[p] + 1 != p) val[pre[p] + 1] += t;
                if(val[pre[p] + 1] + val[pre[p]] <= 0) break;
                if(pre[p] == 0) break;
                t = val[pre[p] + 1] + val[pre[p]];
                p = pre[p];val[p] = t;
                pre[suf[p]] = pre[p];suf[pre[p]] = suf[p];
            }
            pre[suf[i - 1]] = pre[i - 1];
            suf[pre[i - 1]] = suf[i - 1];
        }
    }
    int64 ans = dp[0][1];
    for(int i = 1 ; i <= N ; ++i) {
        ans = min(dp[1][i] + i + dp[0][i + 1],ans);
    }
    out(ans);enter;
}
int main() {
#ifdef ivorysi
    freopen("f1.in","r",stdin);
#endif
    Init();
    Solve();
    return 0;
}

F - Square

題解

咱們冷靜一下很容易發現若是\(abs(x - y) > 2\)那麼\((x,y)\)上的數加上\((y,x)\)的數確定是偶數
這樣的話咱們統計一下沒被佔的對數,以及若是兩個位置都有值是否合法,假如對數是\(cnt\),最後的答案要乘上\(2^cnt\)it

這樣的話咱們只要對中間那一段\(abs(x - y) <= 2\)的部分dp就行了
咱們記錄中軸線上的點,中軸上的點能夠肯定\((i - 1,i + 1)\)\((i + 1,i - 1)\)的奇偶性
\((i - 1,i - 1)\)\((i,i)\)能夠肯定\((i - 1,i)\)\((i,i - 1)\)的奇偶性,判一下就行class

代碼

#include <bits/stdc++.h>
#define fi first
#define se second
#define pii pair<int,int>
#define mp make_pair
#define pb push_back
#define enter putchar('\n')
#define space putchar(' ')
#define eps 1e-8
#define mo 974711
#define MAXN 100005
//#define ivorysi
using namespace std;
typedef long long int64;
typedef double db;
template<class T>
void read(T &res) {
    res = 0;char c = getchar();T f = 1;
    while(c < '0' || c > '9') {
    if(c == '-') f = -1;
    c = getchar();
    }
    while(c >= '0' && c <= '9') {
    res = res * 10 + c - '0';
    c = getchar();
    }
    res *= f;
}
template<class T>
void out(T x) {
    if(x < 0) {x = -x;putchar('-');}
    if(x >= 10) {
    out(x / 10);
    }
    putchar('0' + x % 10);
}
const int MOD = 998244353;
int N,M;
int a[MAXN],b[MAXN],c[MAXN],dp[MAXN][2];
int d[MAXN][4][4];
map<pii,int> zz;
int inc(int a,int b) {
    return a + b >= MOD ? a + b - MOD : a + b;
}
int mul(int a,int b) {
    return 1LL * a * b % MOD;
}
int fpow(int x,int c) {
    int res = 1,t = x;
    while(c) {
        if(c & 1) res = mul(res,t);
        t = mul(t,t);
        c >>= 1;
    }
    return res;
}
void Init() {
    read(N);read(M);
    for(int i = 1 ; i <= N ; ++i) memset(d[i],-1,sizeof(d[i]));
    for(int i = 1 ; i <= M ; ++i) {
        read(a[i]);read(b[i]);read(c[i]);
        zz[mp(a[i],b[i])] = c[i];
        if(abs(a[i] - b[i]) <= 2) {
            int s = a[i],t = b[i];
            if(s > t) swap(s,t);
            for(int k = s - 1 ; k <= t + 1 ; ++k) {
                if(k < 0 || k > N) continue;
                if(abs(a[i] - k) <= 1 && abs(b[i] - k) <= 1) {
                    d[k][2 - (k - a[i])][2 - (k - b[i])] = c[i];
                }
            }
        }
    }

}
void Solve() {
    int64 cnt = 1LL * N * N;
    if(N == 2) cnt = 0;
    else cnt -= (N - 3) * 5 + 9;
    cnt /= 2;
    for(int i = 1 ; i <= M ; ++i) {
        if(abs(b[i] - a[i]) <= 2) continue;
        if(zz.count(mp(b[i],a[i]))) {
            if((zz[mp(b[i],a[i])] + c[i]) & 1) {puts("0");return;}
            if(a[i] < b[i]) --cnt;
        }
        else --cnt;
    }
    int ans = fpow(2,cnt % (MOD - 1));
    if(zz.count(mp(1,1))) dp[1][zz[mp(1,1)]] = 1;
    else dp[1][0] = dp[1][1] = 1;
    for(int i = 2 ; i <= N ; ++i) {
        int t = 1;
        if(d[i][1][2] == -1 && d[i][2][1] == -1) t = mul(t,2);
        if(d[i][1][3] == -1 && d[i][3][1] == -1 && i != N) t = mul(t,2);
        for(int k = 0 ; k <= 1 ; ++k) {
            if(d[i][2][2] != -1 && d[i][2][2] != k) continue;
            if(d[i][1][3] != -1 && d[i][3][1] != -1 && (d[i][1][3] ^ d[i][3][1]) != k) continue;
            for(int h = 0 ; h <= 1 ; ++h) {
                if(!dp[i - 1][h]) continue;
                if(d[i][1][2] != -1 && d[i][2][1] != -1 && (d[i][2][1] ^ d[i][1][2]) != (k ^ h)) continue;
                dp[i][k] = inc(dp[i][k],mul(t,dp[i - 1][h]));
            }
        }
    }
    ans = mul(ans,inc(dp[N][0],dp[N][1]));
    out(ans);enter;
}
int main() {
#ifdef ivorysi
    freopen("f1.in","r",stdin);
#endif
    Init();
    Solve();
    return 0;
}
相關文章
相關標籤/搜索