• 【AtCoder】ExaWizards 2019


    ExaWizards 2019

    C - Snuke the Wizard

    发现符文的相对位置不变,直接二分某个位置是否到达最左或最右来计算

    #include <bits/stdc++.h>
    #define fi first
    #define se second
    #define pii pair<int,int>
    #define mp make_pair
    #define pb push_back
    #define space putchar(' ')
    #define enter putchar('
    ')
    #define eps 1e-10
    #define MAXN 200005
    //#define ivorysi
    using namespace std;
    typedef long long int64;
    typedef unsigned int u32;
    typedef double db;
    template<class T>
    void read(T &res) {
        res = 0;T f = 1;char c = getchar();
        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,Q;
    char s[MAXN];
    pii op[MAXN];
    int getplace(int p) {
        for(int i = 1 ; i <= Q ; ++i) {
            if(s[p] == 'A' + op[i].fi) {
                p += op[i].se;
            }
        }
        return p;
    }
    int findL() {
        int L = 0,R = N;
        while(L < R) {
            int mid = (L + R + 1) >> 1;
            if(getplace(mid) == 0) L = mid;
            else R = mid - 1;
        }
        return L;
    }
    int findR() {
        int L = 1,R = N + 1;
        while(L < R) {
            int mid = (L + R) >> 1;
            if(getplace(mid) == N + 1) R = mid;
            else L = mid + 1;
        }
        return L;
    }
    void Solve() {
        read(N);read(Q);
        scanf("%s",s + 1);
        char t[5],d[5];
        for(int i = 1 ; i <= Q ; ++i) {
            scanf("%s%s",t + 1,d + 1);
            int a,b;
            if(d[1] == 'L') b = -1;
            else b = 1;
            a = t[1] - 'A';
            op[i] = mp(a,b);
        }
        int L = findL(),R = findR();
        out(R - L - 1);enter;
    }
    int main() {
    #ifdef ivorysi
        freopen("f1.in","r",stdin);
    #endif
        Solve();
        return 0;
    }
    

    D - Modulo Operations

    如果按照我们对值产生贡献的序列一定是一个递减的序列

    我们只要按照值从大到小排序后记录(dp[i][j])为到第i个数取模的数是j的概率是多少

    转移的时候如果对当前值进行取模,则乘上一个(frac{1}{N - i + 1})

    否则取乘一个(frac{N- i}{N - 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 space putchar(' ')
    #define enter putchar('
    ')
    #define eps 1e-10
    #define MAXN 200005
    //#define ivorysi
    using namespace std;
    typedef long long int64;
    typedef unsigned int u32;
    typedef double db;
    template<class T>
    void read(T &res) {
        res = 0;T f = 1;char c = getchar();
        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 = 1000000007;
    int N,X,a[205],fac[205],inv[205];
    int dp[205][100005];
    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;
    }
    void update(int &x,int y) {
        x = inc(x,y);
    }
    void Solve() {
        read(N);read(X);
        for(int i = 1 ; i <= N ; ++i) read(a[i]);
        sort(a + 1,a + N + 1,[](int a,int b){return a > b;});
        fac[0] = 1;
        for(int i = 1 ; i <= N ; ++i) fac[i] = mul(fac[i - 1],i);
        inv[1] = 1;
        for(int i = 2 ; i <= N ; ++i) inv[i] = mul(inv[MOD % i],MOD - MOD / i);
        dp[0][X] = 1;
        for(int i = 1 ; i <= N ; ++i) {
            for(int j = 0 ; j <= X ; ++j) {
                if(j < a[i]) update(dp[i][j],dp[i - 1][j]);
                else {
                    update(dp[i][j % a[i]],mul(dp[i - 1][j],inv[N - i + 1]));
                    update(dp[i][j],mul(dp[i - 1][j],mul(N - i,inv[N - i + 1])));
                }
            }
        }
        int ans = 0;
        for(int j = 0 ; j <= X ; ++j) {
            update(ans,mul(dp[N][j],j));
        }
        ans = mul(ans,fac[N]);
        out(ans);enter;
    }
    int main() {
    #ifdef ivorysi
        freopen("f1.in","r",stdin);
    #endif
        Solve();
        return 0;
    }
    

    E - Black or White

    我们把点画在坐标轴上,每个i相当于画一条斜线,那么如果这个斜线上的点都有让B减少的一步,那么答案就是(frac{1}{2})

    否则处理出剩了多少个白点,和剩了多少个黑点的情况,每条斜线最多涉及两个这样的点,把他们的贡献加上或减掉即可

    #include <bits/stdc++.h>
    #define fi first
    #define se second
    #define pii pair<int,int>
    #define mp make_pair
    #define pb push_back
    #define space putchar(' ')
    #define enter putchar('
    ')
    #define eps 1e-10
    #define MAXN 200005
    //#define ivorysi
    using namespace std;
    typedef long long int64;
    typedef unsigned int u32;
    typedef double db;
    template<class T>
    void read(T &res) {
        res = 0;T f = 1;char c = getchar();
        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 = 1000000007;
    int B,W;
    int fac[MAXN],invfac[MAXN],pw[MAXN];
    int r[MAXN],c[MAXN];
    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 C(int n,int m) {
        if(n < m) return 0;
        return mul(fac[n],mul(invfac[m],invfac[n - m]));
    }
    
    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 Solve() {
        read(B);read(W);
        fac[0] = 1;
        for(int i = 1 ; i <= B + W ; ++i) fac[i] = mul(fac[i - 1],i);
        invfac[B + W] = fpow(fac[B + W],MOD - 2);
        for(int i = B + W - 1 ; i >= 0 ; --i) invfac[i] = mul(invfac[i + 1],i + 1);
        pw[0] = 1;pw[1] = invfac[2];
        for(int i = 2 ; i <= B + W ; ++i) pw[i] = mul(pw[i - 1],pw[1]);
        r[0] = pw[W];
        for(int i = 1; i <= B ; ++i) {
            r[i] = inc(r[i - 1],mul(pw[1],mul(pw[i + W - 1],C(i + W - 1,i))));
        }
        c[0] = pw[B];
        for(int i = 1 ; i <= W ; ++i) {
            c[i] = inc(c[i - 1],mul(pw[1],mul(pw[B - 1 + i],C(B - 1 + i,i))));
        }
        for(int i = 0 ; i < B + W ; ++i) {
            int res = (MOD + 1) / 2;
            if(i >= B) {
                res = inc(res,MOD - mul((MOD + 1) / 2,c[i - B]));
            }
            if(i >= W) {
                res = inc(res,mul((MOD + 1) / 2,r[i - W]));
            }
            out(res);enter;
        }
    
    }
    int main() {
    #ifdef ivorysi
        freopen("f1.in","r",stdin);
    #endif
        Solve();
        return 0;
    }
    
  • 相关阅读:
    第十一周作业
    第十周作业
    第九周作业
    第八周作业
    第九周
    第八周
    第七周
    第六周
    第五周
    实验报告二
  • 原文地址:https://www.cnblogs.com/ivorysi/p/10685429.html
Copyright © 2020-2023  润新知