【AtCoder】AGC025题解
A - Digits Sum
枚举即可
代码
#include <bits/stdc++.h>
#define fi first
#define se second
#define pii pair<int,int>
#define space putchar('\n')
#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('\n')
#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('\n')
#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('\n')
#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('\n')
#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('\n')
#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();
}
【AtCoder】AGC025题解的更多相关文章
- AtCoder ExaWizards2019题解
AtCoder ExaWizards2019题解 AtCoder (因为代码直接用模板写的,可能有点冗长) A.Regular Triangle 给你三根棍子的长度,问你能否用他们组成等边三角形. 什 ...
- KYOCERA Programming Contest 2021(AtCoder Beginner Contest 200) 题解
KYOCERA Programming Contest 2021(AtCoder Beginner Contest 200) 题解 哦淦我已经菜到被ABC吊打了. A - Century 首先把当前年 ...
- AT2370 Piling Up
https://www.luogu.org/jump/atcoder/2370 题解 答案不是\(2^{2m}\)因为每轮的第一次取球可能会不够. 我们可以设\(dp[i][j]\)表示到了第\(i\ ...
- Triple Shift
来源:Atcoder ARC 136 B - Triple Shift (atcoder.jp) 题解:这道题我们不可能去硬模拟(大多数这种题都不能这样去模拟的),然后我们就要去发现特性, 发现把 a ...
- 重修 Slope Trick(看这篇绝对够!)
Slope Trick 算法存在十余载了,但是我没有找到多少拍手叫好的讲解 blog,所以凭借本人粗拙的理解来写这篇文章. 本文除标明外所有图片均为本人手绘(若丑见谅),画图真的不容易啊 qwq(无耻 ...
- AtCoder Regular Contest 094 (ARC094) CDE题解
原文链接http://www.cnblogs.com/zhouzhendong/p/8735114.html $AtCoder\ Regular\ Contest\ 094(ARC094)\ CDE$ ...
- AtCoder ExaWizards 2019 简要题解
AtCoder ExaWizards 2019 简要题解 Tags:题解 link:https://atcoder.jp/contests/exawizards2019 很水的一场ARC啊,随随便便就 ...
- AGC025简要题解
AGC025简要题解 B RGB Coloring 一道简单题,枚举即可. C Interval Game 考虑可以进行的操作只有两种,即左拉和右拉,连续进行两次相同的操作是没有用的. 左拉时肯定会选 ...
- AtCoder Grand Contest 017 题解
A - Biscuits 题目: 给出 \(n\) 个物品,每个物品有一个权值. 问有多少种选取方式使得物品权值之和 \(\bmod\space 2\) 为 \(p\). \(n \leq 50\) ...
随机推荐
- Continuation-passing style
Continuation-passing style 参考书籍: EOPL ( Essentials of Programming Languages, 3rd Edition ) 作者:知乎用户链 ...
- 【刷题】BZOJ 2724 [Violet 6]蒲公英
Description Input 修正一下 l = (l_0 + x - 1) mod n + 1, r = (r_0 + x - 1) mod n + 1 Output Sample Input ...
- 同一台机器安装多个MySQL服务
在同一个服务器上面安装多个MySQL服务,甚至是安装多个不同版本(比如5.7和5.7.5.7和8.0.12),关键在于区分安装目录.数据目录和使用端口等. 可以下面步骤 安装MySQL1 wget h ...
- 解题:UOJ #46 玄学
题面 二进制分组,修改把区间拆开丢在后面,合并的时候归并最后两块:查询在对应节点上二分答案 #include<cstdio> #include<cstring> #includ ...
- 位运算的一种应用 和 hiho1516过河解题报告
初始i=s 每次:i=(i-1) & s 直到i=0 etc.11000100000100000000 10000=10001 & 1100001000=01111 & 110 ...
- jq给单选框 radio添加或删除选中状态
$("#div1 :radio").removeAttr("checked");//删除目标div下所有单选框的选中状态 $("#div1 :radi ...
- ReentrantLock与synchronized
1.ReentrantLock 拥有Synchronized相同的并发性和内存语义,此外还多了 锁投票,定时锁等候和中断锁等候 线程A和B都要获取对象O的锁定,假设A获取了对象O锁,B将等待A释放对O ...
- Qt error ------ 'XXX' has not been declared
1.头文件没加 2.调用函数者的头文件在XXX头文件的下方
- bzoj千题计划211:bzoj1996: [Hnoi2010]chorus 合唱队
http://www.lydsy.com/JudgeOnline/problem.php?id=1996 f[i][j][0/1] 表示已经排出队形中的[i,j],最后一个插入的人在[i,j]的i或j ...
- 数学:拓展Lucas定理
拓展Lucas定理解决大组合数取模并且模数为任意数的情况 大概的思路是把模数用唯一分解定理拆开之后然后去做 然后要解决的一个子问题是求模质数的k次方 将分母部分转化成逆元再去做就好了 这里贴一份别人的 ...