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

    A - Diverse Word

    不到26位就加上一个最小的
    到26位了就搜一下,最多回溯就一次,所以复杂度不大

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #include <ctime>
    #include <vector>
    //#define ivorysi
    #define MAXN 100005
    #define eps 1e-7
    #define mo 974711
    #define pb push_back
    #define mp make_pair
    using namespace std;
    typedef long long int64;
    typedef unsigned int u32;
    typedef double db;
    char s[55],ans[55];
    int N,L;
    bool vis[55];
    bool dfs(int dep) {
    	if(dep > 26) return false;
    	if(!vis[s[dep] - 'a']) {
    		vis[s[dep] - 'a'] = 1;
    		ans[dep] = s[dep];
    		if(dfs(dep + 1)) return true;
    		vis[s[dep] - 'a'] = 0;
    	}	
    	for(int i = s[dep] - 'a' + 1 ; i <= 25 ; ++i) {
    		if(!vis[i]) {
    			L = dep;
    			ans[dep] = 'a' + i;
    			return true;
    		}
    	}
    	return false;
    }
    int main() {
    #ifdef ivorysi
        freopen("f1.in","r",stdin);
    #endif
        scanf("%s",s + 1);
        N = strlen(s + 1);
        if(N != 26) {
        	for(int i = 1 ; i <= N ; ++i) vis[s[i] - 'a'] = 1;
        	for(int i = 1 ; i <= N ; ++i) putchar(s[i]);
        	for(int i = 0 ; i <= 25 ; ++i) {
        		if(!vis[i]) {
        			putchar('a' + i);
        			break;
        		}
        	}
        	putchar('
    ');
        }
        else {
        	if(!dfs(1)) puts("-1");
        	else {
        		for(int i = 1 ; i <= L ; ++i) putchar(ans[i]);
        		putchar('
    ');
        	}
        }
    }
    

    B - GCD Sequence

    3 4 5都特判输出
    根据30000我们猜测每三个数里要有两个,或者每六个数里有四个
    我们根据这些数%6的余数分成0 2 3 4 ,6减去他们和他们自己都不互质,所以考虑这么构造

    但是我们希望我们的总和是6的倍数,我们算出当前%6的余数再修改某个点使得总和是6的倍数即可

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #include <ctime>
    #include <vector>
    //#define ivorysi
    #define MAXN 20005
    #define eps 1e-8
    #define mo 974711
    #define pb push_back
    #define mp make_pair
    #define pii pair<int,int>
    #define fi first
    #define se second
    using namespace std;
    typedef long long int64;
    typedef unsigned int u32;
    typedef double db;
    const int64 MOD = 998244353;
    int N;
    int c = 0,ans[MAXN],S;
    
    int main() {
    #ifdef ivorysi
        freopen("f1.in","r",stdin);
    #endif
        scanf("%d",&N);
        if(N == 3) puts("2 5 63");
        else if(N == 4) puts("2 5 20 63");
        else if(N == 5) puts("2 5 20 30 63");
        else {
    	for(int i = 0 ; i <= 4999 ; ++i) {
    	    ans[++c] = 6 * i + 2,ans[++c] = 6 * i + 3,ans[++c] = 6 * i + 4,ans[++c] = 6 * i + 6;
    	}
    	for(int i = 1 ; i <= N ; ++i) S = (S + ans[i]) % 6;
    	if(S == 5) {
    	    ans[6] = 6 * 4999 + 4;
    	}
    	else if(S == 3) {
    	    ans[6] = 6 * 5000;
    	}
    	else if(S == 2){
    	    ans[5] = 6 * 5000;
    	}
    	for(int i = 1 ; i <= N ; ++i) printf("%d%c",ans[i]," 
    "[i == N]);
        }
        return 0;
    }
    

    C - Remainder Game

    显然第k个如果不加,比他小的都放进去都比它优

    所以我们枚举每个k,每次把比它小的k都加进去,看看是否合法

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #include <ctime>
    #include <vector>
    //#define ivorysi
    #define MAXN 20005
    #define eps 1e-8
    #define mo 974711
    #define pb push_back
    #define mp make_pair
    #define pii pair<int,int>
    #define fi first
    #define se second
    using namespace std;
    typedef long long int64;
    typedef unsigned int u32;
    typedef double db;
    const int64 MOD = 998244353;
    int N;
    int a[55],b[55];
    int s[55],cnt,ans[55];
    bool vis[55];
    void Init() {
        scanf("%d",&N);
        for(int i = 1 ; i <= N ; ++i) scanf("%d",&a[i]);
        for(int i = 1 ; i <= N ; ++i) scanf("%d",&b[i]);
    }
    bool check(int x) {
        memset(vis,0,sizeof(vis));
        vis[a[x]] = 1;
        for(int i = 1 ; i <= cnt ; ++i) {
    	for(int j = s[i] ; j <= 50 ; ++j) {
    	    if(vis[j]) vis[j % s[i]] = 1;
    	}
        }
        if(vis[b[x]]) return true;
        return false;
    }
    void Solve() {
        cnt = 0;
        for(int i = 50 ; i >= 1 ; --i) s[++cnt] = i;
        for(int i = 1 ; i <= N ; ++i) {
    	if(!check(i)) {puts("-1");return;}
        }
        for(int i = 50 ; i >= 1 ; --i) {
    	cnt = 0;
    	for(int j = 50 ; j >= i ; --j) {
    	    if(ans[j]) s[++cnt] = j;
    	}
    	for(int j = i - 1 ; j >= 1 ; --j) s[++cnt] = j;
    	for(int j = 1 ; j <= N ; ++j) {
    	    if(!check(j)) {
    		ans[i] = 1;
    		break;
    	    }
    	} 
        }
        int64 res = 0;
        for(int i = 50 ; i >= 1 ; --i) {
    	if(ans[i]) res |= 1LL << i;
        }
        printf("%lld
    ",res);
    }
    int main() {
    #ifdef ivorysi
        freopen("f1.in","r",stdin);
    #endif
        Init();
        Solve();
        return 0;
    }
    

    D - Shopping

    也就是求我们最多转多少圈,输出乘上2×L就好

    我们对于每个位置求一个二元组((x,y))
    对于(t)处理成取模圈长之后的
    (x = 0)表示从左边来,下一次火车经过的时候是从右边来,(x = 1)表示从左边来,下一次火车经过的时候是从左边来
    (y = 0)表示从右边来,下一次火车经过的时候从左边来,(y = 1)表示从右边来,下一次火车经过的时候从右边来
    显然我(x = 1)从左边进要多绕一圈,(y = 1)从右边要多绕一圈

    ((1,1))的点可以直接删除,然后答案累加上1

    然后对于((0,1)(0,1)(0,1)(0,0)(1,0)(1,0))这样的形状,显然不能通过任何一个点走到另一个点而不加任何额外的花费

    所用的圈数就是车站的个数 + 1
    如果是(0,0)或者(0,1)作为结尾,且后面没有任何其余的车站时,就是圈数就是车站的个数

    实际上,我们会有很多((0,0)(0,1))((1,0)(0,0))((0,0)(0,0))这样的形状,我们把他们两两搭配起来就好,圈数+1
    要把((0,0))和别的搭配完了再把((0,0))两两搭配,这样减少的圈最多,并且尽量不配最右一个点

    #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 MAXN 300005
    //#define ivorysi
    using namespace std;
    typedef long long int64;
    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,tot,sta[MAXN],top;
    int64 L,x[MAXN],t[MAXN],ans;
    pii p[MAXN];
    bool vis[MAXN];
    
    
    void Solve() {
        read(N);read(L);
        for(int i = 1 ; i <= N ; ++i) read(x[i]);
        for(int i = 1 ; i <= N ; ++i) {
    	read(t[i]);
    	ans += t[i] / (2 * L);
    	t[i] %= (2 * L);
    	if(t[i] == 0) p[i] = mp(1,1);
    	else p[i] = mp(t[i] > 2 * (L - x[i]),t[i] > 2 * x[i]);
        }
        for(int i = 1 ; i <= N ; ++i) {
    	if(p[i].fi == 1 && p[i].se == 1) {
    	    vis[i] = 1;
    	    if(t[i] != 0) ++ans;
    	}
        }
        top = 0;
        for(int i = 1 ; i <= N ; ++i) {
    	if(!vis[i]) {
    	    if(p[i].fi == 1 && p[i].se == 0) {
    		sta[++top] = i;
    	    }
    	    if(p[i].fi == 0 && p[i].se == 0) {
    		if(top) {
    		    vis[i] = 1;vis[sta[top]] = 1;
    		    --top;++ans;
    		}
    	    }
    	}
        }
        top = 0;
        for(int i = 1; i < N ; ++i) {
    	if(!vis[i]) {
    	    if(p[i].fi == 0 && p[i].se == 0) {
    		sta[++top] = i;
    	    }
    	    if(p[i].fi == 0 && p[i].se == 1) {
    		if(top) {
    		    vis[i] = 1;vis[sta[top]] = 1;
    		    --top;++ans;
    		}
    	    }
    	}
        }
        top = 0;
        for(int i = 1 ; i < N ; ++i) {
    	if(!vis[i]) {
    	    if(p[i].fi == 0 && p[i].se == 0) {
    		if(top) {
    		    vis[i] = 1;vis[sta[top]] = 1;
    		    --top;++ans;
    		}
    		else sta[++top] = i;
    	    }
    	}
        }
        if(!vis[N] && p[N].fi == 0) {
    	for(int i = 1 ; i < N - 1 ; ++i) {
    	    if(!vis[i] && p[i].se == 0) {
    		vis[i] = 1;vis[N] = 1;++ans;break;
    	    }
    	}
        }
        for(int i = 1 ; i <= N ; ++i) {
    	if(!vis[i]) ++ans;
        }
        if(!vis[N]) {
    	if(p[N].fi == 1 && p[N].se == 0) ++ans;
        }
        else ++ans;
        out(ans * 2 * L);
    }
    int main() {
    #ifdef ivorysi
        freopen("f1.in","r",stdin);
    #endif
        Solve();
    }
    

    E - Median Replace

    这个E怎么那么水???
    和上一道D题比起来简直画风不一样……
    分还一样???

    我们显然要贪心地把连着三个0变成一个0

    如果开头有两个连续的1,我们一定可以使得最后的答案是1

    如果开头是一个0,我们一定会把它弄走,而且它的合并一定是和它后面连续的两个

    那么我们就可以记dp状态为(dp[i][j][h][0/1])表示当前有j个0,开头有h个1,有没有出现形状01

    然后转移就是每次加一个0
    形状01是010,合成一个0
    两个0和零个0都会变成1个0
    一个0变成两个0

    每次加一个1
    如果有两个0会变成一个0
    如果有一个0会变成01
    如果没有0就累加一个1
    如果有01会累加一个1

    #include <bits/stdc++.h>
    #define fi first
    #define se second
    #define pii pair<int,int>
    #define space putchar(' ')
    #define enter putchar('
    ')
    #define mp make_pair
    #define pb push_back
    //#define ivorysi
    #define MAXN 300005
    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 = 1000000007;
    int dp[MAXN][3][2][2],sum[MAXN],ans,N;
    char s[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 Solve() {
        scanf("%s",s + 1);
        N = strlen(s + 1);
        for(int i = N ; i >= 1 ; --i) {
            sum[i] = sum[i + 1] + (s[i] == '?');
        }
        dp[0][0][0][0] = 1;
        for(int i = 1 ; i <= N ; ++i) {
            int t = 0;
    
            for(int j = 0 ; j <= 2 ; ++j) {
                for(int h = 0 ; h <= 1 ; ++h) {
                    for(int k = 0 ; k <= 1 ; ++k) {
                        if(!dp[i - 1][j][h][k]) continue;
                        if(s[i] == '0' || s[i] == '?') {
                            if(k) update(dp[i][1][h][0],dp[i - 1][j][h][k]);
                            else {
                                if(j == 1) update(dp[i][2][h][0],dp[i - 1][j][h][k]);
                                else update(dp[i][1][h][0],dp[i - 1][j][h][k]);
                            }
                        }
                        if(s[i] == '1' || s[i] == '?') {
                            if(k) {
                                if(h) update(t,dp[i - 1][j][h][k]);
                                else update(dp[i][0][h + 1][0],dp[i - 1][j][h][k]);
                            }
                            else {
                                if(j == 1) update(dp[i][0][h][1],dp[i - 1][j][h][k]);
                                if(j == 2) update(dp[i][1][h][0],dp[i - 1][j][h][k]);
                                if(j == 0) {
                                    if(h) update(t,dp[i - 1][j][h][k]);
                                    else update(dp[i][0][h + 1][0],dp[i - 1][j][h][k]);
                                }
                            }
                        }
                    }
                }
            }
            update(ans,mul(t,fpow(2,sum[i + 1])));
        }
        update(ans,inc(dp[N][0][1][1],dp[N][0][1][0]));
        out(ans);enter;
    }
    int main() {
    #ifdef ivorysi
        freopen("f1.in","r",stdin);
    #endif
        Solve();
        return 0;
    }
    

    F - Checkers

    一道结论题

    很显然的一点是,我们相当于给每个点上填上(pm 2^j)

    然后一个什么样的序列是合法的呢就是对于某一个位权(i)
    如果我们可以通过改变所有(2^i)前面的符号,可以达成所有(0 leq j leq i)使得他们的和等于(1),那么这个集合就合法
    可以用归纳法证,每次多一个新的(2^i)

    这样的话我们可以记一个(dp[i][j])表示确定了(i)位的值,所有数的和是(1 + j * V),我们上一个加的最大的2的次幂是(frac{V}{2}),因为(2 * j)是偶数所以总可以变成(0)
    答案就是(dp[N][0])为了处理负数可以把第二维整体向前平移(N)

    #include <bits/stdc++.h>
    #define fi first
    #define se second
    #define pii pair<int,int>
    #define space putchar(' ')
    #define enter putchar('
    ')
    #define mp make_pair
    #define MAXN 100005
    //#define ivorysi
    using namespace std;
    typedef long long int64;
    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);
    }
    const int MOD = 1000000007;
    int N;
    int dp[55][105],inv[55],invfac[55],fac[55];
    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]));
    }
    void update(int &x,int y) {
        x = inc(x,y);
    }
    void Solve() {
        read(N);
        inv[1] = 1;
        for(int i = 2 ; i <= N ; ++i) inv[i] = mul(inv[MOD % i],MOD - MOD / i);
        fac[0] = invfac[0] = 1;
        for(int i = 1 ; i <= N ; ++i) {
    	fac[i] = mul(fac[i - 1],i);
    	invfac[i] = mul(invfac[i - 1],inv[i]);
        }
        dp[1][N] = 1;
        dp[1][N - 1] = 1;
        for(int i = 1 ; i <= N ; ++i) {
    	for(int j = -i ; j <= i ; ++j) {
    	    for(int k = max(1,abs(j)) ; k <= N ; ++k) {
    		if(i + k > N) break;
    		for(int h = 0 ; h <= k ; ++h) {
    		    if((j + 2 * h - k) % 2) continue;
    		    int val = (j + 2 * h - k) / 2;
    		    if(val < -N || val > N) continue;
    		    update(dp[i + k][val + N],mul(dp[i][j + N],mul(C(i + k,k),C(k,h))));
    		}
    	    }
    	}
        }
        out(dp[N][N]);enter;
    }
    int main() {
    #ifdef ivorysi
        freopen("f1.in","r",stdin);
    #endif
        Solve();
    }
    
  • 相关阅读:
    ubuntu远程windows桌面
    spring boot 给返回值加状态 BaseData
    spring boot 拦截异常 统一处理
    IntelliJ IDEA spring boot 远程Ddbug调试
    IntelliJ IDEA 常用插件
    spring boot 请求地址带有.json 兼容处理
    spring boot 接口返回值去掉为null的字段
    spring boot 集成disconf
    Spring boot 自定义拦截器
    Linux下安装MySQL
  • 原文地址:https://www.cnblogs.com/ivorysi/p/9882557.html
Copyright © 2011-2022 走看看