zoukankan      html  css  js  c++  java
  • 【AtCoder】AGC005

    AGC005

    A - STring

    用一个栈,如果遇到S就弹入,如果遇到T栈里有S就弹出栈顶,否则T在最后的串里,最后计算出的T和栈里剩的S就是答案

    #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);
    }
    char s[MAXN];
    int top,N;
    void Solve() {
        scanf("%s",s + 1);
        N = strlen(s + 1);
        int ans = 0;
        for(int i = 1 ; i <= N ; ++i) {
            if(s[i] == 'T') {
                if(top) --top;
                else ++ans;
            }
            else {
                ++top;
            }
        }
        ans += top;
        out(ans);enter;
    }
    int main() {
    #ifdef ivorysi
        freopen("f1.in","r",stdin);
    #endif
        Solve();
        return 0;
    }
    

    B - Minimum Sum

    就是单调栈求出左边最靠近它且比它小的数,右边最靠近且比它小的数,就可以计算出以这个点为最小值的区间有多少了

    #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,a[MAXN],l[MAXN],r[MAXN];
    int sta[MAXN],top;
    int64 ans = 0;
    void Solve() {
        read(N);
        for(int i = 1 ; i <= N ; ++i) read(a[i]);
        for(int i = 1 ; i <= N ; ++i) {
            while(top && a[sta[top]] > a[i]) --top;
            l[i] = sta[top] + 1;
            sta[++top] = i;
        }
        top = 0;sta[0] = N + 1;
        for(int i = N ; i >= 1 ; --i) {
            while(top && a[sta[top]] > a[i]) --top;
            r[i] = sta[top] - 1;
            sta[++top] = i;
        }
        for(int i = 1 ; i <= N ; ++i) {
            ans += 1LL * (i - l[i] + 1) * (r[i] - i + 1) * a[i];
        }
        out(ans);enter;
    }
    int main() {
    #ifdef ivorysi
        freopen("f1.in","r",stdin);
    #endif
        Solve();
        return 0;
    }
    

    C - Tree Restoring

    最大的A肯定是直径,如果直径是奇数,看看最小值是不是两个,其余的长度必须都大于等于2个

    如果直径是偶数,看看最小值是不是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);
    }
    int D,N,a[MAXN],cnt[MAXN];
    void Solve() {
        read(N);
        for(int i = 1 ; i <= N ; ++i) {read(a[i]);cnt[a[i]]++;}
        for(int i = 1 ; i <= N ; ++i) D = max(D,a[i]);
        if(D & 1) {
            if(cnt[D / 2 + 1] != 2) {puts("Impossible");return;}
            int res = 0;
            for(int i = D / 2 + 1 ; i <= D ; ++i) {
                res += cnt[i];
                if(cnt[i] < 2) {puts("Impossible");return;}
            }
            if(res != N) {puts("Impossible");return;}
        }
        else {
            if(cnt[D / 2] != 1) {puts("Impossible");return;}
            int res = 1;
            for(int i = D / 2 + 1 ; i <= D ; ++i) {
                res += cnt[i];
                if(cnt[i] < 2) {puts("Impossible");return;}
            }
            if(res != N) {puts("Impossible");return;}
        }
        puts("Possible");return;
    }
    int main() {
    #ifdef ivorysi
        freopen("f1.in","r",stdin);
    #endif
        Solve();
        return 0;
    }
    

    D - ~K Perm Counting

    用经典容斥,设(g(i))为至少i个位置不合法的情况

    答案就是(sum_{i = 0}^{n}(-1)^{i}g(i))

    ([1,2K - 1])开头,每(2K)个选择一个构成的这样的序列,这个序列当前的数每个能填什么,之和上一个数选择什么有关,这个可以用一个dp完成,然后可以得到每个序列里至少选了(i)个方案数

    组合起来可以用NTT优化

    #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 2005
    //#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 = 924844033,g = 5,MAXL = (1 << 15);
    
    int N,K;
    int a[MAXN],W[MAXL + 5],f[2][MAXN][2],p[MAXL + 5];
    int ans[MAXL + 5],fac[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;
    }
    void update(int &x,int y) {
        x = inc(x,y);
    }
    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 NTT(int *p,int L,int on) {
        for(int i = 1 , j = L >> 1 ; i < L - 1 ; ++i) {
            if(i < j) swap(p[i],p[j]);
            int k = L >> 1;
            while(j >= k) {
                j -= k;
                k >>= 1;
            }
            j += k;
        }
        for(int h = 2 ; h <= L ; h <<= 1) {
            int wn = W[(MAXL + on * MAXL / h) % MAXL];
            for(int k = 0 ; k < L ; k += h) {
                int w = 1;
                for(int j = k ; j < k + h / 2 ; ++j) {
                    int u = p[j],t = mul(p[j + h / 2],w);
                    p[j] = inc(u,t);
                    p[j + h / 2] = inc(u,MOD - t);
                    w = mul(w,wn);
                }
            }
        }
        if(on == -1) {
            int invL = fpow(L,MOD - 2);
            for(int i = 0 ; i < L ; ++i) p[i] = mul(p[i],invL);
        }
    }
    void Solve() {
        read(N);read(K);
        W[0] = 1;W[1] = fpow(g,(MOD - 1) / MAXL);
        for(int i = 2 ; i < MAXL ; ++i) W[i] = mul(W[i - 1],W[1]);
        int len = 1;
        while(len <= N) len <<= 1;
        ans[0] = 1;
        NTT(ans,len,1);
        for(int i = 1 ; i <= 2 * K ; ++i) {
            memset(f,0,sizeof(f));
            int cur = 0;
            f[cur][0][0] = 1;int cnt = 0;
            for(int j = i ; j <= N ; j += 2 * K) {
                memset(f[cur ^ 1],0,sizeof(f[cur ^ 1]));
                for(int h = 0 ; h <= cnt ; ++h) {
                    update(f[cur ^ 1][h][0],inc(f[cur][h][0],f[cur][h][1]));
                    if(j - K >= 1) update(f[cur ^ 1][h + 1][0],f[cur][h][0]);
                    if(j + K <= N) update(f[cur ^ 1][h + 1][1],inc(f[cur][h][0],f[cur][h][1]));
                }
                ++cnt;
                cur ^= 1;
            }
            memset(p,0,sizeof(p));
            for(int j = 0 ; j <= N ; ++j) {
                p[j] = inc(f[cur][j][0],f[cur][j][1]);
            }
            NTT(p,len,1);
            for(int j = 0 ; j < len ; ++j) {
                ans[j] = mul(ans[j],p[j]);
            }
        }
        NTT(ans,len,-1);
        fac[0] = 1;
        for(int i = 1 ; i <= N ; ++i) fac[i] = mul(fac[i - 1],i);
        int res = 0;
        for(int i = 0 ; i <= N ; ++i) {
            if(i & 1) update(res,MOD - mul(fac[N - i],ans[i]));
            else update(res,mul(fac[N - i],ans[i]));
        }
        out(res);enter;
    }
    int main() {
    #ifdef ivorysi
        freopen("f1.in","r",stdin);
    #endif
        Solve();
        return 0;
    }
    

    E - Sugigma: The Showdown

    观察出-1的条件是先手走到一条红边的某个端点,这个红边的两个端点在蓝边树上的距离大于等于3

    之后我们可以进行深搜,如果可以到某个点,先手和这个点的距离小于后手到达这个的距离就可以走,否则不行

    如果走到特殊点输出-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);
    }
    vector<int> to[2][MAXN];
    int fa[MAXN][20],dep[MAXN];
    int N,X,Y,ans;
    bool flag = 0;
    int lca(int u,int v) {
        if(dep[u] < dep[v]) swap(u,v);
        int l = 18;
        while(dep[u] > dep[v]) {
            if(dep[fa[u][l]] >= dep[v]) {
                u = fa[u][l];
            }
            --l;
        }
        if(u == v) return u;
        l = 18;
        while(fa[u][0] != fa[v][0]) {
            if(fa[u][l] != fa[v][l]) {
                u = fa[u][l];
                v = fa[v][l];
            }
            --l;
        }
        return fa[u][0];
    }
    int dist(int u,int v) {
        return dep[u] + dep[v] - 2 * dep[lca(u,v)];
    }
    void dfs(int u) {
        for(auto t : to[1][u]) {
            if(t != fa[u][0]) {
                dep[t] = dep[u] + 1;
                fa[t][0] = u;
                dfs(t);
            }
        }
    }
    void dfs1(int u,int f,int d) {
        if(u == Y) return;
        ans = max(ans,dep[u] - 1);
        for(auto t : to[0][u]) {
            if(t == f) continue;
            if(dist(u,t) > 2) flag = 1;
            if(d + 1 < dep[t] - 1) dfs1(t,u,d + 1);
        }
    }
    void Solve() {
        read(N);read(X);read(Y);
        int a,b;
        for(int i = 1 ; i < N ; ++i) {
            read(a);read(b);
            to[0][a].pb(b);to[0][b].pb(a);
        }
        for(int i = 1 ; i < N ; ++i) {
            read(a);read(b);
            to[1][a].pb(b);to[1][b].pb(a);
        }
        dep[Y] = 1;
        dfs(Y);
        for(int j = 1 ; j <= 19 ; ++j) {
            for(int i = 1 ; i <= N ; ++i) {
                fa[i][j] = fa[fa[i][j - 1]][j - 1];
            }
        }
        dfs1(X,0,0);
        if(flag) {puts("-1");}
        else {out(2 * ans);enter;}
    }
    int main() {
    #ifdef ivorysi
        freopen("f1.in","r",stdin);
    #endif
        Solve();
        return 0;
    }
    

    F - Many Easy Problems

    我们把一个点的贡献转化为一条边的贡献,因为边的数量是点的数量-1,最后再加上选点方案数(inom{n}{k})即可

    一条边的贡献是(inom{n}{k} - inom{a}{k} - inom{n - a}{k})就是在n个点里选k个点,去掉不合法的情况也就是k个点都在去掉这条边的两个子树里

    然后我们要统计的就是(inom{a}{k} + inom{n - a}{k})

    这个可以转化成(ans_{k} = sum_{i = 1}^{n} b_{i} inom{i}{k})

    (ans_{k} = frac{1}{k!} sum_{i = 1}^{n} b_{i} i! frac{1}{(i - k)!})
    这个数组是可以卷积的,只要把一个倒过来就行
    (f(i) = frac{1}{(n - i)!})
    (g(i) = b_{i}i!)
    (h = g * f)
    (ans_{k} = h(N + k))

    代码

    #include <iostream>
    #include <cstdio>
    #include <vector>
    #include <algorithm>
    #include <cmath>
    #include <cstring>
    #include <map>
    //#define ivorysi
    #define pb push_back
    #define space putchar(' ')
    #define enter putchar('
    ')
    #define mp make_pair
    #define pb push_back
    #define fi first
    #define se second
    #define mo 974711
    #define RG register
    #define MAXN 200005
    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) {putchar('-');x = -x;}
        if(x >= 10) {
    	out(x / 10);
        }
        putchar('0' + x % 10);
    }
    struct node {
        int to,next;
    }E[MAXN * 2];
    int head[MAXN],sumE;
    void add(int u,int v) {
        E[++sumE].to = v;
        E[sumE].next = head[u];
        head[u] = sumE;
    }
    const int MOD = 924844033,L = (1 << 19),G = 5;
    int N,f[L + 5],fac[MAXN],invfac[MAXN],b[L + 5],W[L + 5];
    int mul(int a,int b) {return 1LL * a * b % MOD;}
    int inc(int a,int b) {a = a + b;if(a >= MOD) a -= MOD;return a;}
    int fpow(int x,int c) {
        int t = x,res = 1;
        while(c) {
    	if(c & 1) res = mul(res,t);
    	t = mul(t,t);
    	c >>= 1;
        }
        return res;
    }
    int C(int n,int m) {
        if(n < m) return 0;
        return mul(mul(fac[n],invfac[m]),invfac[n - m]);
    }
    int dfs(int u,int fa) {
        int siz = 1;
        for(int i = head[u] ; i ; i = E[i].next) {
    	int v = E[i].to;
    	if(v != fa) {
    	    siz += dfs(v,u);
    	}
        }
        if(fa != 0) {
    	b[siz]++;
    	b[N - siz]++;
        }
        return siz;
    }
    void NTT(int *a,int LEN,int on) {
        for(int i = 1 , j = LEN / 2 ; i < LEN - 1 ; ++i) {
    	if(i < j) swap(a[i],a[j]);
    	int k = LEN / 2;
    	while(j >= k) {
    	    j -= k;
    	    k >>= 1;
    	}
    	j += k;
        }
        for(int h = 2 ; h <= LEN ; h <<= 1) {
    	int wn = W[(L + on * L / h) % L];
    	for(int k = 0 ; k < LEN ; k += h) {
    	    int w = 1;
    	    for(int j = k ; j < k + h / 2 ; ++j) {
    		int64 u = a[j],t = 1LL * a[j + h / 2] * w;
    		a[j] = (u + t) % MOD;
    		a[j + h / 2] = (u - t + 1LL * MOD * MOD) % MOD;
    		w = mul(w,wn);
    	    }
    	}
        }
        if(on == -1) {
    	int invL = fpow(LEN,MOD - 2);
    	for(int i = 0 ; i < LEN ; ++i) a[i] = mul(a[i],invL);
        }
    }
    void Solve() {
        read(N);
        int u,v;
        for(int i = 1 ; i < N ; ++i) {
    	read(u);read(v);add(u,v);add(v,u);
        }
        dfs(1,0);
        fac[0] = 1;
        for(int i = 1 ; i <= N ; ++i) fac[i] = mul(fac[i - 1],i);
        invfac[N] = fpow(fac[N],MOD - 2);
        for(int i = N - 1 ; i >= 0 ; --i) invfac[i] = mul(invfac[i + 1],i + 1);
        for(int i = 0 ; i <= N ; ++i) f[N - i] = invfac[i];
        for(int i = 1 ; i <= N ; ++i) b[i] = mul(b[i],fac[i]);
        W[0] = 1;W[1] = fpow(G,(MOD - 1) / L);
        for(int i = 2 ; i < L ; ++i) W[i] = mul(W[i - 1],W[1]);
        int t = 1;
        while(t <= 2 * N) t <<= 1;
        NTT(b,t,1);NTT(f,t,1);
        for(int i = 0 ; i < t ; ++i) f[i] = mul(f[i],b[i]);
        NTT(f,t,-1);
        for(int i = 1 ; i <= N ; ++i) {
    	int ans = mul(f[i + N],invfac[i]);
    	ans = inc(mul(N,C(N,i)),MOD - ans);
    	out(ans);enter;
        }
    }
    int main() {
    #ifdef ivorysi
        freopen("f1.in","r",stdin);
    #endif
        Solve();
        return 0;
    }
    
  • 相关阅读:
    Oracle 内存参数调优设置
    查询Oracle正在执行的sql语句及执行该语句的用户
    oracle审计详解
    Oracle数据库的性能调整
    性能监控工具的配置及使用
    windows端5款mysql客户端工具
    Oracle 11g密码过期问题及解决方案
    PLSQL安装、PLSQL汉化、激活
    Mercurial 安装及使用
    Servlet基础(二) Servlet的生命周期
  • 原文地址:https://www.cnblogs.com/ivorysi/p/10890366.html
Copyright © 2011-2022 走看看