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

    A - Digits Sum

    枚举即可

    代码

    #include <bits/stdc++.h>
    #define fi first
    #define se second
    #define pii pair<int,int>
    #define space putchar('
    ')
    #define enter putchar(' ')
    //#define ivorysi
    using namespace std;
    typedef long long int64;
    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){putchar('-');x = -x;}
    	if(x >= 10) out(x / 10);
    	putchar('0' + x % 10);
    }
    int N;
    int main() {
    #ifdef ivorysi
    	freopen("f1.in","r",stdin);
    #endif
    	read(N);
    	int ans = 0x7fffffff;
    	for(int i = 1 ; i < N ; ++i) {
    		int A = i,B =  N - i;
    		int tmp = 0;
    		while(A) {tmp += A % 10;A /= 10;}
    		while(B) {tmp += B % 10;B /= 10;}
    		ans = min(ans,tmp);
    	}
    	out(ans);enter;
    }
    

    B - RGB Coloring

    枚举有几个A,可以算出有几个B
    可以看作给序列染两次色(每个块可以有两种颜色),被同时染了红和蓝的就是绿色算就好了

    代码

    #include <bits/stdc++.h>
    #define fi first
    #define se second
    #define pii pair<int,int>
    #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;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){putchar('-');x = -x;}
    	if(x >= 10) out(x / 10);
    	putchar('0' + x % 10);
    }
    const int MOD = 998244353;
    int N,fac[MAXN],invfac[MAXN],inv[MAXN];
    int64 A,B,K;
    int mul(int a,int b) {
    	return 1LL * a * b % MOD;
    }
    int inc(int a,int b) {
    	return a + b >= MOD ? a + b - MOD : a + b;
    }
    int C(int n,int m) {
    	if(m > n) return 0;
    	return mul(fac[n],mul(invfac[m],invfac[n - m]));
    }
    int main() {
    #ifdef ivorysi
    	freopen("f1.in","r",stdin);
    #endif
    	read(N);read(A);read(B);read(K);
    	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]);
    	}
    	int ans = 0;
    	for(int i = 0 ; i <= N ; ++i) {
    		if(K < i * A) break;
    		if((K - i * A) % B != 0) continue;
    		int s = i,t = (K - i * A) / B;
    		ans = inc(ans,mul(C(N,s),C(N,t)));
    	}
    	out(ans);enter;
    }
    

    C - Interval Game

    每次都往最左和最右拉
    枚举第一次是往左还是往右

    代码

    #include <bits/stdc++.h>
    #define fi first
    #define se second
    #define pii pair<int,int>
    #define space putchar('
    ')
    #define enter putchar(' ')
    #define MAXN 100005
    //#define ivorysi
    using namespace std;
    typedef long long int64;
    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){putchar('-');x = -x;}
    	if(x >= 10) out(x / 10);
    	putchar('0' + x % 10);
    }
    const int MOD = 998244353;
    int N,ans;
    pii S[MAXN];
    int id[2][MAXN];
    bool vis[MAXN];
    bool cmp1(int a,int b) {
    	return S[a].fi < S[b].fi;
    }
    bool cmp2(int a,int b) {
    	return S[a].se < S[b].se;
    }
    int main() {
    #ifdef ivorysi
    	freopen("f1.in","r",stdin);
    #endif
    	read(N);
    	for(int i = 1 ; i <= N ; ++i) {
    		read(S[i].fi);read(S[i].se);
    		id[0][i] = i;id[1][i] = i;
    	}
    	sort(id[0] + 1,id[0] + N + 1,cmp1);
    	sort(id[1] + 1,id[1] + N + 1,cmp2);
    	int64 ans = 0;
    	memset(vis,0,sizeof(vis));
    	int p[2];p[0] = N,p[1] = 1;
    	int pos = 0;int64 tmp = 0;
    	if(S[id[0][N]].fi > 0) {
    		vis[id[0][p[0]]] = 1;--p[0];
    	 	tmp += abs(S[id[0][N]].fi - pos);
    		pos = S[id[0][N]].fi;
    		int cur = 1;
    		while(1) {
    			if(cur == 1) {
    				while(p[cur] <= N && vis[id[cur][p[cur]]]) ++p[cur];
    				if(p[cur] > N) break;
    				if(S[id[cur][p[cur]]].se >= pos) break;
    				tmp += abs(S[id[cur][p[cur]]].se - pos);
    				pos = S[id[cur][p[cur]]].se;
    				vis[id[cur][p[cur]]] = 1;
    			}
    			else {
    				while(p[cur] >= 1 && vis[id[cur][p[cur]]]) --p[cur];
    				if(p[cur] < 1) break;
    				if(S[id[cur][p[cur]]].fi <= pos) break;
    				tmp += abs(S[id[cur][p[cur]]].fi - pos);
    				pos = S[id[cur][p[cur]]].fi;
    				vis[id[cur][p[cur]]] = 1;
    			}
    			cur ^= 1;
    		}
    		tmp += abs(pos);
    	}
    	ans = max(ans,tmp);
    	memset(vis,0,sizeof(vis));
    	pos = 0;tmp = 0;p[0] = N;p[1] = 1;
    	if(S[id[1][1]].se < 0) {
    		vis[id[1][1]] = 1;++p[1];
    		tmp += abs(S[id[1][1]].se - pos);
    		pos = S[id[1][1]].se;
    		int cur = 0;
    		while(1) {
    			if(cur == 1) {
    				while(p[cur] <= N && vis[id[cur][p[cur]]]) ++p[cur];
    				if(p[cur] > N) break;
    				if(S[id[cur][p[cur]]].se >= pos) break;
    				tmp += abs(S[id[cur][p[cur]]].se - pos);
    				pos = S[id[cur][p[cur]]].se;
    				vis[id[cur][p[cur]]] = 1;
    			}
    			else {
    				while(p[cur] >= 1 && vis[id[cur][p[cur]]]) --p[cur];
    				if(p[cur] < 1) break;
    				if(S[id[cur][p[cur]]].fi <= pos) break;
    				tmp += abs(S[id[cur][p[cur]]].fi - pos);
    				pos = S[id[cur][p[cur]]].fi;
    				vis[id[cur][p[cur]]] = 1;
    			}
    			cur ^= 1;
    		}
    		tmp += abs(pos);
    	}
    	ans = max(ans,tmp);
    	out(ans);enter;
    }
    

    D - Choosing Points

    我们根据(D_1)(D_2)连边,会得到两个二分图
    为什么是二分图呢
    对于(D)是奇数来说,((x,y))((x + s,y + t))连边,我们很容易发现这两个点横纵坐标加和奇偶性不同
    对于(D)是偶数来说,还是根据奇偶性染色,我们发现边只在颜色相同的块里有,我们把(sqrt{2})当单位长度,再一次对每个联通块二分图染色,这样不断消去2,最后就会得到一个二分图

    那么每个点在两个图里一共四种搭配,那么根据鸽巢原理,最多的那个颜色必然有超过(N^2)个点

    代码

    #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 MAXN 100005
    //#define ivorysi
    using namespace std;
    typedef long long int64;
    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){putchar('-');x = -x;}
    	if(x >= 10) out(x / 10);
    	putchar('0' + x % 10);
    }
    int N,D[2];
    struct node {
    	int to,next;
    }E[10000005];
    int head[400005],sumE,dx[] = {-1,-1,1,1},dy[] = {1,-1,-1,1};
    int col[400005],cr[400005],cnt[5];
    int to_int(pii p) {
    	return p.fi * 2 * N + p.se;
    }
    void add(int u,int v) {
    	E[++sumE].to = v;
    	E[sumE].next = head[u];
    	head[u] = sumE;
    }
    void dfs(int u) {
    	if(col[u] == -1) col[u] = 0;
    	for(int i = head[u] ; i ; i = E[i].next) {
    		int v = E[i].to;
    		if(col[v] == -1) {col[v] = col[u] ^ 1;dfs(v);}
    	}
    }
    int main() {
    #ifdef ivorysi
    	freopen("f1.in","r",stdin);
    #endif
    	read(N);read(D[0]);read(D[1]);
    	for(int t = 0 ; t <= 1 ; ++t) {
    		memset(head,0,sizeof(head));sumE = 0;
    		for(int x = 0 ; x < 2 * N ; ++x) {
    			if(D[t] < x * x) break;
    			int y = sqrt(D[t] - x * x);
    			if(y * y != D[t] - x * x) continue;
    			for(int i = 0 ; i < 2 * N ; ++i) {
    				for(int j = 0 ; j < 2 * N ; ++j) {
    					for(int k = 0 ; k < 4 ; ++k) {
    						int tx = i + dx[k] * x,ty = j + dy[k] * y;
    						if(tx >= 0 && tx < 2 * N && ty >= 0 && ty < 2 * N) {
    							add(to_int(mp(i,j)),to_int(mp(tx,ty)));
    						}
    					}
    				}
    			}
    		}
    		memset(col,-1,sizeof(col));
    		for(int i = 0 ; i < 4 * N * N ; ++i) {
    			if(col[i] == -1) dfs(i);
    			cr[i] = cr[i] << 1 | col[i];
    		}
    	}
    	for(int i = 0 ; i < 4 * N * N ; ++i) ++cnt[cr[i]];
    	int t = 0;
    	for(int i = 1 ; i < 4 ; ++i) {
    		if(cnt[i] > cnt[t]) t = i;
    	}
    	int a = N * N;
    	for(int i = 0 ; i < 4 * N * N ; ++i) {
    		if(!a) break;
    		if(cr[i] == t) {
    			out(i / (2 * N));space;out(i % (2 * N));enter;
    			--a;
    		}
    	}
    }
    

    E - Walking on a Tree

    答案最大是(min(c_i,2))的和,(c_i)是每条边被覆盖了几次

    构造方法是每次选一个叶子u
    找到连着u的唯一一条边v,((u,v))如果这条边覆盖的链有1条或0条,那么就删掉u
    否则将所有覆盖着u的链两两组合((u,a))((u,b))变成((a,b))通过((a,b))的方向来判断((u,a))((u,b))的方向

    代码

    #include <bits/stdc++.h>
    #define fi first
    #define se second
    #define pii pair<int,int>
    #define space putchar(' ')
    #define enter putchar('
    ')
    #define MAXN 4005
    #define mp make_pair
    #define pb push_back
    //#define ivorysi
    using namespace std;
    typedef long long int64;
    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,M;
    struct node {
        int to,next;
    }E[MAXN * 2];
    int head[MAXN],sumE,d[MAXN],dep[MAXN],fa[MAXN],cnt[MAXN];
    void add(int u,int v) {
        E[++sumE].to = v;
        E[sumE].next = head[u];
        head[u] = sumE;
    }
    void dfs(int u) {
        dep[u] = dep[fa[u]] + 1;
        for(int i = head[u] ; i ; i = E[i].next) {
    	int v = E[i].to;
    	if(v != fa[u]) {
    	    fa[v] = u;
    	    dfs(v);
    	}
        }
    }
    int col(int u,int v) {
        if(dep[u] < dep[v]) swap(u,v);
        while(dep[u] != dep[v]) {
    	++cnt[u];
    	u = fa[u];
        }
        while(u != v) {
    	++cnt[u];++cnt[v];
    	u = fa[u];v = fa[v];
        }
    }
    vector<pii > Process(vector<pii> pth) {
        int x = 0;
        for(int i = 1 ; i <= N ; ++i) {
    	if(d[i] == 1) {
    	    x = i;break;
    	}
        }
        d[x]--;int u = 0;
        for(int i = head[x] ; i ; i = E[i].next) {
    	int v = E[i].to;
    	if(d[v]) {
    	    --d[v];u = v;break;
    	}
        }
        if(!u) return pth;
        vector<pii > pass,npth;
        vector<int> id;
        id.clear();pass.clear();npth.clear();
        int pos[2005];
        int t,h;
        memset(pos,-1,sizeof(pos));
        for(int i = 0 ; i < pth.size() ; ++i){
    	if(pth[i].fi == x && pth[i].se != x) {
    	    pass.pb(pth[i]);id.pb(i);
    	}
    	else if(pth[i].fi != x && pth[i].se == x) {
    	    swap(pth[i].fi,pth[i].se);
    	    pass.pb(pth[i]);id.pb(i);
    	}
    	else {
    	    npth.pb(pth[i]);
    	    pos[i] = npth.size() - 1;
    	}
        }
        t = npth.size();
        if(!pass.size()) return Process(pth);
        bool flag = 0;
        for(int i = 0 ; i < pass.size() ; i += 2) {
    	if(i + 1 >= pass.size()) break;
    	if(pass[i].se == pass[i + 1].se) swap(pth[id[i]].fi,pth[id[i]].se);
    	npth.pb(mp(pass[i].se,pass[i + 1].se));
    	pos[id[i]] = npth.size() - 1;
    	pos[id[i + 1]] = npth.size() - 1;
        }
        if(pass.size() & 1) {
    	flag = 1;
    	h = pass.size() - 1;
    	npth.pb(mp(u,pass[h].se));
    	pos[id[h]] = npth.size() - 1;
        }
        npth = Process(npth);
        for(int i = 0 ; i < pth.size() ; ++i) {
    	if(pos[i] < t) {pth[i] = npth[pos[i]];}
    	else {
    	    if(flag && i == id[h]) {
    		if(npth[pos[i]].fi != u) swap(pth[i].fi,pth[i].se);
    	    }
    	    else {
    		if(npth[pos[i]].fi != npth[pos[i]].se && npth[pos[i]].fi == pth[i].se) swap(pth[i].fi,pth[i].se);
    	    }
    	}
        }
        return pth;
    }
    void Solve() {
        read(N);read(M);
        int a,b;
        for(int i = 1 ; i < N ; ++i) {
    	read(a);read(b);
    	add(a,b);add(b,a);
    	++d[a];++d[b];
        }
        dfs(1);
        vector<pii > v;
        for(int i = 1 ; i <= M ; ++i) {
    	read(a);read(b);
    	v.pb(mp(a,b));col(a,b);
        }
        v = Process(v);
        int ans = 0;
        for(int i = 1 ; i <= N ; ++i) ans += min(2,cnt[i]);
        out(ans);enter;
        for(int i = 0 ; i < v.size() ; ++i) {
    	out(v[i].fi);space;out(v[i].se);enter;
        }
    }
    int main() {
    #ifdef ivorysi
        freopen("f1.in","r",stdin);
    #endif
        Solve();
    }
    

    F - Addition and Andition

    我们可以从高位到低位处理每一位的移动

    如果两位是(1,1),我们用一个栈从栈顶到栈底下标递增维护((0,1))((1,0))的形状
    进位分成三种
    11,s和t都进位
    10,s进位,t不进位
    01,s不进位,t进位

    如果有11,我们看看走的步数能不能走到一个((1,0))((0,1)),再计算下一种进位方式
    如果有10,或01,我们看看下一个形状是不是就在它的下一位,然后再计算下一种计算方式

    如果都不成立,那么如果进位是11,移动到最后的位置并把这一位都写成1
    如果进位是10和01,那么放进栈里

    每次走两步必然会少一个元素,所以复杂度是(O(n))

    #include <bits/stdc++.h>
    #define fi first
    #define se second
    #define pii pair<int,int>
    #define space putchar(' ')
    #define enter putchar('
    ')
    #define MAXN 2000005
    #define mp make_pair
    #define pb push_back
    //#define ivorysi
    using namespace std;
    typedef long long int64;
    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 + 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);
    }
    struct node {
        int id,par;
    }sta[MAXN],tmp[MAXN];
    int N,M,K,top,cnt,ns[MAXN],nt[MAXN],as[MAXN],at[MAXN];
    char s[MAXN],t[MAXN];
    void Solve() {
        read(N);read(M);read(K);
        scanf("%s",s + 1);scanf("%s",t + 1);
        reverse(s + 1,s + N + 1);reverse(t + 1,t + M + 1);
        for(int i = 1 ; i <= N ; ++i) ns[i] = s[i] - '0';
        for(int i = 1 ; i <= M ; ++i) nt[i] = t[i] - '0';
        int T = max(N,M);
        for(int i = T ; i >= 1 ; --i) {
    	if(ns[i] == 1 && nt[i] == 1) {
    	    int op = K,pos = i,x = 3;cnt = 0;
    	    while(top) {
    		if(x == 3) {
    		    if(op >= sta[top].id - pos) {
    			op -= sta[top].id - pos;
    			pos = sta[top].id;
    			tmp[++cnt] = (node){pos,x ^ sta[top].par};
    			x = x & sta[top].par;
    		    }
    		    else break;
    		}
    		else if(x != 0){
    		    if(sta[top].id == pos + 1) {
    			pos = sta[top].id;
    			if(x ^ sta[top].par) x = 3;
    			else x = x & sta[top].par;
    		    }
    		    else break;
    		}
    		else break;
    		--top;
    	    }
    	    if(x != 0 && x != 3) {
    		++pos;
    		tmp[++cnt] = (node){pos,x};
    	    }
    	    else if(x) {
    		pos += op;
    		as[pos] = at[pos] = 1;
    	    }
    	    for(int j = cnt ; j >= 1 ; --j) sta[++top] = tmp[j];
    	}
    	else {
    	    if(ns[i] || nt[i]) {
    		sta[++top] = (node){i,ns[i] << 1 | nt[i]};
    	    }
    	}
        }
        for(int i = 1 ; i <= top ; ++i) {
    	as[sta[i].id] = (sta[i].par >> 1) & 1;
    	at[sta[i].id] = sta[i].par & 1;
        }
        int c = T + K;
        while(as[c] == 0) --c;
        for(int i = c ; i >= 1 ; --i) {out(as[i]);}
        enter;
        c = T + K;
        while(at[c] == 0) --c;
        for(int i = c ; i >= 1 ; --i) {out(at[i]);}
        enter;
    }
    int main() {
    #ifdef ivorysi
        freopen("f1.in","r",stdin);
    #endif
        Solve();
    }
    
  • 相关阅读:
    amaze(妹子~) 好像挺好玩
    php 获取图片base64编码格式数据
    一些laravel博文
    微信移动端(wap)开发调试工具
    深入理解控制反转(IoC)和依赖注入(DI)
    使用 composer 下载更新卸载类库
    ionic ui 框架
    laravel 添加 404 页面
    laravel 调试模式及日志配置
    iOS-方法之+ initialize 与 +load
  • 原文地址:https://www.cnblogs.com/ivorysi/p/9823073.html
Copyright © 2011-2022 走看看