• 【AtCoder】CADDi 2018


    C - Product and GCD

    题解

    直接分解质因数,然后gcd每次多一个质因数均摊到每个(N)上的个数

    代码

    #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('
    ')
    #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

    题解

    这题简直了,比赛完两分钟就想出来,比赛时候硬是怎么也想不出来

    如果全是偶数肯定后手必胜,因为先手在哪个堆拿一个后手在这个堆跟一个
    如果某个堆是奇数先手可以把局面转变为全是偶数然后自己当后手

    所以有奇数先手必胜
    全是偶数后手必胜

    #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('
    ')
    #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])
    否则后一个数肯定会变大,后一个数变大会引起之后的一些值变大,如果和后面相连且已经增加过的位置都会同时加上这个数,同时这个增加了还会使后面没有增加过的位置增加
    这个可以用链表维护,因为每个点被增加后就被删除了,所以链表维护每次暴力更新就好

    代码

    #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('
    ')
    #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)

    这样的话我们只要对中间那一段(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))的奇偶性,判一下就行

    代码

    #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('
    ')
    #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;
    }
    
  • 相关阅读:
    Pivot Table 实现详解(一)
    VSTS 离线源码版本辅助工具
    早上发现还是问题不断
    VSTS 离线源码版本辅助工具源码
    C#单元测试
    长沙招聘若干 ASP.NET 开发人员(长期有效)
    解析判定数据有效性表达式的存储过程 for SQLServer
    提高 SNAP 网页预览图的采集速度
    用了2年多快3年的老ASUS本子出了点小问题了
    模拟一下细胞的繁殖(CSDN号召帖)
  • 原文地址:https://www.cnblogs.com/ivorysi/p/10167652.html
Copyright © 2020-2023  润新知