zoukankan      html  css  js  c++  java
  • 【AtCoder】AGC026 题解

    A - Colorful Slimes 2

    找相同颜色的一段,然后答案加上段长除2下取整

    代码

    #include <iostream>
    #include <cstdio>
    using namespace std;
    int N;
    int a[105];
    int main() {
        scanf("%d",&N);
        for(int i = 1 ; i <= N ; ++i) {
            scanf("%d",&a[i]);
        }
        int ans = 0;
        int cnt = 0;
        for(int i = 1 ; i <= N ; ++i) {
            if(a[i] != a[i - 1]) {
                ans += cnt / 2;
                cnt = 0;
            }
            ++cnt;
        }
        ans += cnt / 2;
        printf("%d
    ",ans);
    }
    

    B - rng_10s

    题解

    如果A < B一定不可以
    如果C>=B并且D>=B显然一定可以
    如果D < B那么一定不可以
    然后如果A大于C,那么就买几个B使得A减到C以下,如果减的过程中买不到了,那么就不可以

    每次买完还需要补货的时候相当于从A开始,每次加上B和D的gcd,如果这个值落在了C和B之间,那么就不合法了

    代码

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <vector>
    #include <cstring>
    //#define ivorysi
    #define fi first
    #define se second
    #define MAXN 25005
    #define enter putchar('
    ')
    #define space putchar(' ')
    typedef long long int64;
    using namespace std;
    template <class T>
    void read(T &res) {
        res = 0;char c = getchar();T f = 1;
        while(c < '0' || c > '9') {
            c = getchar();
            if(c == '-') f = -1;
        }
        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;}
        if(x >= 10) {
            out(x / 10);
        }
        putchar('0' + x % 10);
    }
    int T;
    int64 A,B,C,D;
    int64 gcd(int64 a,int64 b) {
        return b == 0 ? a : gcd(b,a % b);
    }
    void Solve() {
        read(A);read(B);read(C);read(D);
        if(A < B) {puts("No");}
        else {
            if(C >= B && D >= B) puts("Yes");
            else if(D < B) puts("No");
            else {
                if(A > C) {
                    int64 t = (A - C - 1) / B + 1;
                    if(t > A / B) {
                        puts("No");return;
                    }
                    A -= B * t;
                }
                int64 g = gcd(D % B,B);
                if((C + 1 - A - 1) / g + 1 == (B - A - 1) / g + 1) puts("Yes");
                else puts("No");
            }
        }
    }
    int main() {
    #ifdef ivorysi
        freopen("f1.in","r",stdin);
    #endif
        read(T);
        while(T--) {
            Solve();
        }
    }
    

    C - String Coloring

    题解

    直接折半搜索即可
    用哈希表维护前半部分拆分方式的两个字符串的哈希值
    再枚举后一半的拆分方式查哈希表即可

    代码

    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <algorithm>
    #define enter putchar('
    ')
    #define space putchar(' ')
    #define fi first
    #define se second
    #define ba 47
    #define mo 999999137
    #define mod 974711
    //#define ivorysi
    #define pii pair<int,int>
    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);
    }
    struct Hash {
        char t[20];
        int64 val;
        int len;
        friend bool operator < (const Hash &a,const Hash &b) {
    	return a.val < b.val;
        }
        friend bool operator == (const Hash &a,const Hash &b) {
    	if(a.val != b.val) return false;
    	if(a.len != b.len) return false;
    	for(int i = 1 ; i <= a.len ; ++i) {
    	    if(a.t[i] != b.t[i]) return false;
    	}
    	return true;
        }
    }B[1000005];
    int cnt;
    int64 e[55];
    struct Mmp {
        struct node {
    	int next,v;
    	int64 x;
        }E[1000005];
        int head[mod + 5],sumE;
        void clear() {
    	memset(head,0,sizeof(head));
    	sumE = 0;
        }
        void add(int64 x,int v) {
    	int u = x % mod;
    	E[++sumE].x = x;
    	E[sumE].v = v;
    	E[sumE].next = head[u];
    	head[u] = sumE;
        }
        void Insert(int64 x) {
    	int u = x % mod;
    	for(int i = head[u] ; i ; i = E[i].next) {
    	    if(E[i].x == x) {E[i].v++;return;}
    	}
    	add(x,1);
        }
        int Query(int64 x) {
    	int u = x % mod;
    	for(int i = head[u]; i ; i = E[i].next) {
    	    if(E[i].x == x) return E[i].v;
    	}
    	return 0;
        }
    }M1,M2;
    int64 Calc(char *s,int l) {
        int64 res = 0;
        for(int i = 1 ; i <= l ; ++i) {
    	res += (s[i] - 'a' + 1) * e[i] % mo;
    	res %= mo;
        }
        return res;
    }
    void Insert(char *s,int l) {
        ++cnt;
        for(int i = 1 ; i <= l ; ++i) B[cnt].t[i] = s[i]; 
        B[cnt].len = l;B[cnt].val = Calc(s,l);
    }
    int N;
    char s[55];
    void Solve() {
        read(N);
        e[0] = 1;
        for(int i = 1 ; i <= N ; ++i) e[i] = e[i - 1] * ba % mo;
        scanf("%s",s + 1);
        char t1[25],t2[25];
        int c1,c2;
        for(int S = 0 ; S < (1 << N) ; ++S) {
    	c1 = c2 = 0;
    	int T = 0;
    	for(int i = 1 ; i <= N ; ++i) {
    	    if(S >> (i - 1) & 1) t1[++c1] = s[i];
    	    else {t2[++c2] = s[i];T |= (1 << i - 1);}
    	}
    	if(S > T) continue;
    	if(c1) Insert(t1,c1);
    	if(c2) Insert(t2,c2);
        }
        sort(B + 1,B + cnt + 1);
        cnt = unique(B + 1,B + cnt + 1) - B - 1;
        M1.clear();M2.clear();
        for(int i = 1 ; i <= cnt ; ++i) {
    	M1.add(B[i].val,i);
        }
        for(int S = 0 ; S < (1 << N) ; ++S) {
    	c1 = c2 = 0;
    	for(int i = 1 ; i <= N ; ++i) {
    	    if(S >> (i - 1) & 1)  t1[++c1] = s[i];
    	    else {t2[++c2] = s[i];}
    	}
    	int d1 = 0,d2 = 0;
    	if(c1) d1 = M1.Query(Calc(t1,c1));
    	if(c2) d2 = M1.Query(Calc(t2,c2));
    	M2.Insert(1LL * d1 * (cnt + 1) + d2);
        }
        int64 ans = 0;
        for(int S = 0 ; S < (1 << N) ; ++S) {
    	c1 = c2 = 0;
    	for(int i = N + 1 ; i <= 2 * N ; ++i) {
    	    if(S >> (i - N - 1) & 1) t1[++c1] = s[i];
    	    else {t2[++c2] = s[i];}
    	}
    	reverse(t1 + 1,t1 + c1 + 1);
    	reverse(t2 + 1,t2 + c2 + 1);
    	int d1 = 0,d2 = 0;
    	if(c1) d1 = M1.Query(Calc(t1,c1));
    	if(c2) d2 = M1.Query(Calc(t2,c2));
    	ans += M2.Query(1LL * d1 * (cnt + 1) + d2);
        }
        out(ans);enter;
    }
    int main() {
    #ifdef ivorysi
        freopen("f1.in","r",stdin);
    #endif
        Solve();
    }
    

    D - Histogram Coloring

    题解

    我们考虑从上往下,对于每个分离的直方图的横列进行dp,然后再把他们合起来

    我们发现,如果直方图不是10101010或0101010101的形式,那么以下所有列就只有一种放置方法

    那么我们记录两个值,一个是直方图最下面一行填的是1010101或01010101,记为dp[S][1],一个是所有的方案数记为dp[S][2]

    转移方法是对于一个列数一样的矩形块
    dp[S][1]是它上面所有的直方图dp[S][1]乘起来,然后再乘上2的行数次幂
    dp[S][2]我们认为是如果是010101或101010,那么下面对应的有两种方式,剩下的只有一种,其余的方块随便填,下面每一行是上一行取反
    是上面所有直方图的(dp[T][1] + dp[T][2])乘起来,然后再乘上2的剩余方块数的幂
    但是dp[S][2]也应该包括相邻两行有相同的情况,我们就再加上dp[S][1],同时减掉dp[S][1]中我们每行都不同的情况

    代码

    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <algorithm>
    #define enter putchar('
    ')
    #define space putchar(' ')
    #define fi first
    #define se second
    #define mp make_pair
    #define ba 47
    #define mo 999999137
    #define mod 974711
    //#define ivorysi
    #define pii pair<int,int>
    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 h[105];
    bool vis[105];
    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 update(int &x,int y) {
        x = inc(x,y);
    }
    pii Solve(int l,int r,int v) {
        int minv = 1e9;
        for(int i = l ; i <= r ; ++i) minv = min(minv,h[i]);
        int p,cnt = 0;
        pii res = mp(1,1);
        for(int i = l ; i <= r ; ++i) {
    	if(h[i] > minv) ++cnt;  
        }
        for(int i = l ; i <= r ; ++i) {
    	if(h[i] > minv) {
    	    p = i;
    	    while(p < r && h[p + 1] > minv) ++p;
    	    pii f = Solve(i,p,minv);
    	    res.fi = mul(res.fi,f.fi);
    	    res.se = mul(res.se,inc(f.se,f.fi));
    	    i = p;
    	}
        }
        int t = mul(res.fi,2);
        res.se = mul(res.se,fpow(2,r - l + 1 - cnt));
        res.fi = mul(res.fi,fpow(2,minv - v));
        res.se = inc(res.se,inc(res.fi,MOD - t));
        return res; 
    }
    void Solve() {
        read(N);
        for(int i = 1 ; i <= N ; ++i) {read(h[i]);}
        pii ans = Solve(1,N,0);
        out(ans.se);enter;
    }
    int main() {
    #ifdef ivorysi
        freopen("f1.in","r",stdin);
    #endif
        Solve();
    }
    

    E - Synchronized Subsequence

    题解

    如果b在a前就一直选,选到某个最大的a的位置会更改成一段a在b前
    如果这个a在b前是最后一部分就取到所有的abababab...前,否则就跳过这一段
    具体就用string维护一下后缀能取到的max字符串就好了

    代码

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <vector>
    #include <cmath>
    #include <queue>
    #include <ctime>
    #include <map>
    #include <set>
    #define fi first
    #define se second
    #define pii pair<int,int>
    //#define ivorysi
    #define mp make_pair
    #define pb push_back
    #define enter putchar('
    ')
    #define space putchar(' ')
    #define MAXN 6005
    using namespace std;
    typedef long long int64;
    typedef double db;
    typedef unsigned int u32;
    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 - '0' + c;
    		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);
    }
    namespace task {
    	char s[MAXN];
    	int N,a[MAXN],b[MAXN],tota,totb,pos[MAXN];
    	string str[MAXN];
    	bool vis[MAXN];
    	void Init() {
    		read(N);
    		scanf("%s",s + 1);
    		tota = 0;totb = 0;
    		for(int i = 1 ; i <= 2 * N ; ++i) {
    			if(s[i] == 'a') {a[++tota] = i;pos[i] = tota;}
    			else {b[++totb] = i;pos[i] = totb;}
    		}
    	}
    	void Solve() {
    		str[2 * N + 1] = "";
    		for(int i = 2 * N ; i >= 1 ; --i) {
    			str[i] = max(str[i],str[i + 1]);
    			string t = "";
    			int p = pos[i];
    			if(s[i] == 'a' && a[p] < b[p]) {
    				str[i] = max(str[i],"ab" + str[b[p] + 1]);
    			}
    			else if(s[i] == 'b' && b[p] < a[p]) {
    				memset(vis,0,sizeof(vis));
    				int maxv = a[p];
    				for(int j = i ; j <= maxv ; ++j) {
    					if(s[j] == 'b') {
    						p = pos[j];
    						vis[b[p]] = 1;vis[a[p]] = 1;
    						maxv = max(a[p],maxv);
    					}
    					if(vis[j]) t += s[j];
    				}
    				t += str[maxv + 1];
    				str[i] = max(str[i],t);
    			}
    		}
    		cout<<str[1]<<endl;
    	}
    }
    int main() {
    #ifdef ivorysi
    	freopen("f1.in","r",stdin);
    #endif
    	task::Init();
    	task::Solve();
    	return 0;
    }
    

    F - Manju Game

    题解

    我们把整个序列黑白染色变成
    BWBWBWBW的形式

    如果是偶数的话
    先手可以保证自己得到全部的B或全部的W
    后手可以在先手做出选择后,保证自己得到另一种颜色的所有
    这样的话,相当于先手得到黑白颜色中较多的那个,后手得到较少的那个

    如果是奇数的话
    先手还是可以保证自己得到所有B
    那么先手选W的话解会不会更优
    先手在选B之后,便不可能再选W,如果某一次B进行完了以后先手选了W结果更优,后手可以撤销上一次操作,使得先后手所拿到的物品相反,结果更劣

    先手假如可以选(W_1,W_2,W_3...W_k)如果,我们能取的区间如果全取B的话,这个区间的B - W是最小的,所以我们限定一下这个区间B - W的最小值,二分一下,然后用一个dp判断即可

    代码

    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <algorithm>
    #define enter putchar('
    ')
    #define space putchar(' ')
    #define fi first
    #define se second
    #define mp make_pair
    //#define ivorysi
    #define pii pair<int,int>
    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);
    }
    int N;
    int64 a[300005],sum[300005][2];
    bool check(int64 mid) {
        int64 t = 0; 
        for(int i = 2 ; i <= N ; i += 2) {
    	if(sum[i - 1][1] - sum[i - 1][0] + t >= mid) {
    	    t = max(sum[i][0] - sum[i][1],t);
    	}
        }
        if(sum[N][1] - sum[N][0] + t >= mid) return true;
        return false;
    }
    void Solve() {
        read(N);
        for(int i = 1 ; i <= N ; ++i) read(a[i]);
        int64 L = 0,R = 0;
        for(int i = 1 ; i <= N ; ++i) {
    	R += a[i];L -= a[i];
    	sum[i][0] = sum[i - 1][0];
    	sum[i][1] = sum[i - 1][1];
    	sum[i][i & 1] += a[i];
        }
        if(N % 2 == 0) {
    	out(max(sum[N][0],sum[N][1]));space;out(min(sum[N][0],sum[N][1]));enter;
    	return;
        }
        while(L < R) {
    	int64 mid = (L + R + 1) >> 1;
    	if(check(mid)) L = mid;
    	else R = mid - 1;
        }
        int64 a = L + sum[N][0];
        int64 b = sum[N][0] + sum[N][1] - a;
        out(a);space;out(b);enter;
    }
    int main() {
    #ifdef ivorysi
        freopen("f1.in","r",stdin);
    #endif
        Solve();
    }
    
  • 相关阅读:
    Unity Behaviors for Interception
    Unity Method Dependency Injection
    Unity的AdditionalInterfaces问题
    Unity的三种Interceptor
    C#实现office文档转换为PDF或xps的一些方法
    多级菜单CSS+DIV
    应用软件系统架构设计的“七种武器”(转)
    AjaxModalPopupExtender
    越来越苦,献给狗日的小温
    NHibernate教程
  • 原文地址:https://www.cnblogs.com/ivorysi/p/9775312.html
Copyright © 2011-2022 走看看