牛客小白月赛30
前言
这次比赛新生还有几个打的不错的,嗯至少明年能组一个队能打,我这次感觉不在状态
其实这次比赛的题没有前几次小白月赛难,AK的人也多,题目偏简单,好了不说废话了
黑白边
解题思路:
这题是一道最小生成树的题,prim最小生成树会T,得用Kruskal并且是路径压缩优化的,因为出题人卡了时间
当然这题也能用并查集过,比较Kruskal的本质就是并查集嘛,(当然也要路径压缩优化)
鉴于是并查集/最小生成树板子题,我不过多讲解,尽量选取黑边联通就行
Code:
#include<bits/stdc++.h>
using namespace std;
const int N = 2e5+10;
int fa[N];
int n,m;
int cnt;
void init(int n) {//初始化
for(int i = 1;i <= n; ++i) {
fa[i] = i;
}
}
int find(int x) {
int t = x;
while(t!=fa[t]) {
t=fa[t];
}
//这里就是路径压缩
while(x!=fa[x]) {
int temp = fa[x];
fa[x] = t;
x = temp;
}
return x;
}
int merge(int a,int b) {//将两个点合并
a = find(a),b = find(b);
if(a != b) {
fa[b] = a;
cnt--;//表示的是剩余的未联通的点的个数
return 1;
}
return 0;
}
struct Node {//边
int a,b,c;
}edge[N];
bool cmp(Node a,Node b) {//cmp排序函数
return a.c<b.c;
}
int main()
{
scanf("%d%d",&n,&m);
init(n);
cnt = n;
for(int i = 0;i < m;++i) {
scanf("%d%d%d",&edge[i].a,&edge[i].b,&edge[i].c);
}
bool fg = false;
sort(edge,edge+m,cmp);
int sum = 0;
for(int i = 0;i < m; ++i) {
int tt = merge(edge[i].a,edge[i].b);
if(tt)
sum+=edge[i].c;
if(cnt == 1) {//如果全部联通,那么就直接退出循环
fg = true;
break;
}
}
if(fg) {
printf("%d
",sum);
}
else
puts("-1");
return 0;
}
最好的宝石
解题思路:
很明显是一道线段树的题目,单点修改,区间查询,属于有手就行的题目(然鹅我没手T^T,昨天写了一手线段树,写炸了)
这题先挖坑,以后再填。先放上一个大佬(新都大三那位)的Code
Code:
#include <bits/stdc++.h>
#define reg register
#define ios ios::sync_with_stdio(false)
using namespace std;
typedef pair<int,int> pii;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int eps = 1e-10;
const int maxn = 5e6 + 10;
const int mod = 1e9 + 7;
struct SegmentTree{
int val[maxn ];
int cnt[maxn];
#define lson rt<<1,l,mid
#define rson rt<<1|1,mid + 1, r
void pushup(int rt)
{
int mx = 0,ct;
if(val[rt << 1] > val[rt << 1 | 1]) {
mx = val[rt << 1];
ct = cnt[rt << 1];
}
else if(val[rt << 1] < val[rt << 1 | 1]){
mx = val[rt << 1 | 1];
ct = cnt[rt << 1 | 1];
}
else{
mx = val[rt << 1 | 1];
ct = cnt[rt << 1 | 1] + cnt[rt << 1];
}
val[rt] = mx;
cnt[rt] = ct;
}
void build(int rt,int l,int r)
{
if(l == r){
val[rt] = 0;
cnt[rt] = 1;
return ;
}
int mid = l + r >> 1;
build(lson);
build(rson);
}
void update(int rt,int l,int r,int p,int v)
{
if(l == r){
val[rt] = v;
return ;
}
int mid = l + r >> 1;
if(p <= mid) update(lson,p,v);
else update(rson,p,v);
pushup(rt);
}
int query(int rt, int l,int r,int ql,int qr)
{
if(ql <= l && r <= qr){
return val[rt];
}
int res = 0;
int mid = l + r >> 1;
if(qr <= mid) res = max(res,query(lson,ql,qr));
else if(ql > mid) res = max(res,query(rson,ql,qr));
else res = max(res,max(query(lson,ql,mid),query(rson,mid + 1,qr)));
return res;
}
int querycnt(int rt, int l,int r,int ql,int qr,int mx)
{
if(ql <= l && r <= qr){
if(mx == val[rt]){
return cnt[rt];
}
return 0;
}
int res = 0;
int mid = l + r >> 1;
if(qr <= mid) res += querycnt(lson,ql,qr,mx);
else if(ql > mid) res += querycnt(rson,ql,qr,mx);
else res = res + querycnt (lson,ql,mid,mx) + querycnt(rson,mid + 1,qr,mx);
return res;
}
}seg;
int main()
{
int n,m;
cin>>n>>m;
seg.build(1,1,n);
for(int i = 1;i <= n;++i){
int tmp;
scanf("%d",&tmp);
seg.update(1,1,n,i,tmp);
}
while(m--){
string s;
int x,y;
cin>>s>>x>>y;
if(s == "Ask"){
int mx = seg.query(1,1,n,x,y);
int cnt = seg.querycnt(1,1,n,x,y,mx);
printf("%d %d
",mx,cnt);
}
else{
seg.update(1,1,n,x,y);
}
}
return 0;
}
滑板上楼梯
解题思路:
每次可以跳3阶或者1阶,因为要求跳的最小的次数那么不难发现我们3 1 3 1的跳这样以跳两次为一个周期,最后剩余的台阶
肯定是0或者1或者2或者3的,我们可以发现如果剩下的台阶数为1或者3,那么直接跳一次就行,如果剩下的台阶数是2那么,跳
两次就行,如果剩下的台阶数是0,那么就不用跳(因为数据有0的情况),我们可以先把周期数求出来,然后乘2就是前面跳的次数
然后我们在对剩下的台阶数进行判断最后加起来就行
Code:
#include<bits/stdc++.h>
using namespace std;
long long n,m;
int main()
{
long long sum = 0;
cin>>n;
long long k = n/4;
n -= k * 4;
sum += k*2;
if(n== 1 || n == 3)
sum += 1;
else if(n == 2)
sum += 2;
cout<<sum<<endl;
return 0;
}
GCD
解题思路:
题目说在集合S种找到一个最小的k,任选S中k个元素作为子集T,子集T中存在两不同元素x、y,使得(GCD(x,y)>1)
很显然什么时候才能满足这个条件呢,就是看S元素中素数的个数,如果素数的个数占了n-1个(n表示的是集合S中的元素)
那么肯定没有k能满足条件的,因为无论怎么选两数,他们的GCD都是1,所以问题转化为了找集合S的素数个数那么可以
直接从1到n暴力判断是否是素数,当然也可以用埃氏筛或者欧拉筛做(可以,但没必要),最后找到了素数的个数k,因为元素1
不是素数,但是元素1必须要加入T集合中,并且还需要一个非素数的元素,所以最后(ans=k+2)
暴力判断素数Code:
#include<bits/stdc++.h>
using namespace std;
bool isprime(int x) {//暴力判断素数
//注意我这里,如果x=1的时候我判断它是素数,这样就能方便我们后续操作
for(int i = 2;i *i <= x; ++i) {
if(x%i==0)
return false;
}
return true;
}
int main()
{
int n;
cin>>n;
int sum = 0;
int k ;
for(int i = 1;i <= n; ++i) {//查找素数的个数
if(isprime(i))
sum++;
}
if(sum == n) {//因为我们把1也认为是素数了
k = -1;
}
else {
k = sum+1;//加的这个1表示的是非素数的元素
}
cout<<k<<endl;
return 0;
}
欧拉筛Code:
#include<bits/stdc++.h>
using namespace std;
const int N = 100005;
int prime[N];
bool vis[N];
int get_prime(int n) {
memset(vis,true,sizeof vis);
memset(prime,0,sizeof prime);
vis[0] = vis[1] = false;
for(int i = 2; i <= n; ++i) {
if (vis[i]) {
prime[++prime[0]] = i;
}
for(int j = 1;j <= prime[0] && i*prime[j] <= n; ++j) {
vis[i * prime[j]] = false;
if (i % prime[j] == 0)
break;
}
}
return prime[0];//返回的是素数的个数
}
int main()
{
int n;
cin>>n;
int k = get_prime(n);
if(k == n-1)//判断素数的个数是否是n-1个
cout<<-1<<endl;
else
cout<<k+2<<endl;//素数的个数+1元素+非素数元素
return 0;
}
牛牛的加法
解题思路:
题目描述有问题,至少说有歧义吧,我以为不进位是说的是最大位不进位,然鹅出题人想表达的意思是每个位置加和都不进位
那这样的话就更简单了,我们直接从后往前加和然后对当前的数进行取余10,最后在再从前往后输出,注意这里有个坑点
不能要前缀0,并且如果全为0的情况,直接输出0
Code:
#include<bits/stdc++.h>
using namespace std;
const int N = 200010;
int c[N];
void slove(string a, string b) {//a的长度 < b
int len1 = a.size();
int len2 = b.size();
//把元素往后移一位(开始我以为要进位,所以这样操作的,这个可以不用)
for(int i = len1;i > 0; --i) a[i] = a[i-1];
for(int i = len2;i > 0; --i) b[i] = b[i-1];
int i = len2;
//然后从后往前开始加和并且不能进位
for(int j = len1;j > 0; --j,--i) {
int k = a[j] -'0' + b[i] - '0';
c[i] += k;
c[i] %= 10;//直接对10取模,不用进位
}
while(i) {//把b剩下的值放进c中
c[i] += b[i]-'0';
i--;
}
i = 1;
bool fg = false;//是否是全为0
while(c[i] == 0 && i <= len2) i++;
for(;i <= max(len1,len2);++i) {
cout<<c[i];
fg = true;//如果有不为0的输出,则将fg改变状态
}
if(!fg)//如果全为0,则直接输出0
cout<<0;
cout<<"
";
}
int main()
{
string a,b;
cin>>a>>b;
int len1 = a.size();
int len2 = b.size();
if(len1 < len2)
slove(a,b);
else
slove(b,a);
return 0;
}
石子合并
解题思路:
相邻的两堆石子,取走价值最小的那一堆,得到的价值是两堆之和,不难发现,我们找到所有石子中价值最大的那一堆
然后让该石子和其他所有石子进行取的操作得到的价值是最大的,因为我们每次取走石子的到的价值是取走石子的价值
加上最大石子的价值,如果我们不和最大石子进行取操作的话,得到的价值肯定是小于和最大石子进行取操作的值
所以问题转化为了求所有石子中价值最大的k,然后把其他石子的价值加起来sum,最后的到的总价值是(sum+k imes (n-1))
Code:
#include<bits/stdc++.h>
using namespace std;
const int N =200005;
int a[N],n,max_;//max_表示的是最大元素的值
int main()
{
long long sum=0;
scanf("%d",&n);
for(int i = 0;i < n; ++i)
{
scanf("%d",&a[i]);
max_ = max(max_,a[i]);
sum += a[i];
}
if(n>=2)
printf("%lld",(n-2) * max_ + sum);//这里减去2是因为上面循环的时候已经加过一次max_
//也就是说最大值已经加在了sum里面
else //注意n=1的情况直接输出0
puts("0");
return 0;
}
滑板比赛
解题思路:
牛牛有n个动作每个动作的华丽值为a[i],牛妹有m个动作,每个动作的华丽值为b[i],要想牛牛赢得次数尽可能多,因为每
个动作只能比较一次那么我们就要让牛牛华丽值最高的动作依次和牛妹的华丽值最高的动作依次比较,然后判断牛牛能赢多少场,
时间复杂度为(O(M)),我们设一个i指针(数组的位置)表示牛牛当前的华丽值的位置,j表示牛妹华丽值的位置,我们遍历牛妹的华丽值
如果牛牛华丽值大于牛妹的华丽值,那么让牛牛的i往后移一位,每次比较完牛妹的指针往后移一位,看代码可能要清楚点
Code:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N = 200005;
bool cmp(int a,int b) {
return a>b;
}
int a[N],b[N];
int main()
{
ios::sync_with_stdio(false);
int n,m;
cin>>n>>m;
for(int i = 0;i < n; ++i) {
cin>>a[i];
}
for(int i = 0;i < m; ++i) {
cin>>b[i];
}
sort(a,a+n,cmp);//对牛牛的华丽值进行排序
sort(b,b+m,cmp);//对牛妹的华丽值进行排序
int ans = 0;//牛牛胜利的次数
//为什么要遍历牛妹的华丽值呢,因为每个动作只能比较一次
for(int i = 0,j = 0;i < m; ++i) {//j表示的是牛牛的第(j+1)大的华丽值的位置
if(a[j] > b[i]) {//如果牛牛的华丽值大于牛妹的华丽值那么让牛牛的位置往后移
j++;
ans++;//胜利次数+1
}
}
cout<<ans;
return 0;
}
第 k 小
解题思路:
要找到第k小的数,并且可以往数组里面添加元素,那么我们可以维护一个大顶堆的优先队列,让队列的元素个数一直保持 <= k个
如果队列元素的个数小于k那么输出-1,否则输出队列顶端的元素,每次插入元素的时候如果插入后元素个数大于k那么就pop
时间复杂度为(n(logn))
Code:
#include<cstdio>
#include<algorithm>
#include<queue>
#include<cstring>
using namespace std;
const int N = 200005;
int n,m,k;
int a[N];
priority_queue<int> que;
int main()
{
scanf("%d%d%d",&n,&m,&k);
for(int i = 1;i <= n; ++i) {
scanf("%d",&a[i]);
}
sort(a+1,a+n+1);
for(int i = 1;i <= n && i <= k; ++i) {//把前k小的元素放进队列
que.push(a[i]);
}
int loc = min(n,k);
while(m--) {
int x,y;
scanf("%d",&x);
if(x == 1) {//插入元素
scanf("%d",&x);
que.push(x);
loc++;
if(loc > k) {//当队列元素中个数大于k
loc--;
que.pop();
}
}
else {
if(loc == k)//如果队列元素个数刚好等于k,那么输出队首元素
printf("%d
",que.top());
else//否则就没有第k小元素
printf("-1
");
}
}
return 0;
}
区间异或
解题思路:
看了下数据n=3e3的,我们可以通过一个(O(N^2))的预处理,求得每个长度的异或最大值,对于每次查询只需要(O(N))的
查询时间就够了,具体操作看代码,总时间复杂度为(O(N^2+M imes N))
Code:
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
using namespace std;
const int N = 3005;
int n,m;
int a[N];
vector<int> V;
int main()
{
scanf("%d%d",&n,&m);
for(int i = 1;i <= n; ++i) scanf("%d",&a[i]);
for(int i = 1;i <= n; ++i) {
int ans = 0, mx = 0;//这里的mx表示的是长度为i的时候的区间最大异或值
for(int j = 1; j <= n; ++j) {
ans ^= a[j];
if(j > i) ans ^= a[j - i];//两个相同的数进行异或操作为0
//这样就让我们把每次异或的区间长度控制为i
mx = max(mx,ans);
}
V.push_back(mx);
}
int x;
while(m--) {
scanf("%d",&x);
int ans = -1;//我先让位置为-1,表示查不到的情况
for(int i = 0;i < V.size(); ++i) {//从小到大查询
if(V[i] >= x) {//查到第一个大于等于x的位置直接保存位置,然后跳出循环
ans = i+1;
break;
}
}
printf("%d
",ans);//输出查找到的位置
}
return 0;
}
小游戏
解题思路:
题目说拿走x之后x-1和x+1变得不能拿,那么我们就可以将这个问题转化为动态规划,第一眼我看成了01背包
其实这是一个线性dp,cnt[i]表示的是第分数为i的个数,dp[i]表示的是直到第i个数取走的最大分数,那么就能列出状态转移方程如下
Code:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N = 200005;
ll dp[N];
int cnt[N];
int main()
{
int n,x;
scanf("%d",&n);
for(int i = 0;i < n; ++i) {
scanf("%d",&x);
cnt[x]++;
}
dp[1] = 1LL * cnt[1];
for(int i = 2;i <= 200000; ++i) {
dp[i] = max(dp[i-1],dp[i-2] + 1LL * cnt[i] * i);
}
cout<<dp[200000]<<endl;
return 0;
}
总结
题目总体偏简单,但是也不是语法题,比较适合才入门的新生,当然我这次做的挺烂的,有些题还是要仔细想想,不要直接莽
平时的练习倒无所谓,真正比赛的时候有罚时,还是要提高一下写题的准确性
/*
.
`;|$&@&$%%%|||%%$&@&%' .
'$$%|!!!;;;!!!||%$@@&%;' .:%&&%!:::::::::::::::::::::|!..
.||:::::::::::::::::::::::;|$@$!` `|&$!::::::::::::::::::::::::::::!|'.
;%:::::::::::::::::::::::::::::::;|&&!` `|&$!:::::::::::::::::::::::::::::::::!%:.
`||:::::::::::::::::::::::::::::::::::::!$&|' '%&|::::::::::::::::::::::::::::::::::::::;%;.
:%;:::::::::::::::::::::::::::::::::::::::::!$@&;. '%@%;::::::::::::::::::::::::::::::::::::::::::%!`
!%:::::::::::::::::::::::::::::::::::::::::::::!%&@&!. .!&@$|:::::::::::::::::::::::::::::::::::::::::::::%!`
.||:::::::::::::::::::::::::::::::::::::::::::::::;|$$&@&;.'%@@@@$!``%@&$%!:::::::::::::::::::::::::::::::::::::::::::::::|!'
`|!:::::::::::::::::::::::::::::::::::::::::::::::;!|%$$&@$;:::::;|&@&$%!:::::::::::::::::::::::::::::::::::::::::::::::::||'
:|;::::::::::::::::::::::::::::::::::::::::::;%&@@@@$%|!!;:::::;!|%&@##@&$$%!:::::::::::::::::::::::::::::::::::::::::::::||:
:%;:::::::::::::::::::::::::::::::::::!%&@$|;'````.```..```...```..``..```:|&@@|;:::::::::::::::::::::::::::::::::::::::::||:
:%;::::::::::::::::::::::::::::::!$&|:`.`..................................`````;$&|;:::::::::::::::::::::::::::::::::::::||'
:%;::::::::::::::::::::::::::|&$:`.........``.................................`.````;$$!::::::::::::::::::::::::::::::::::||'
'|!::::::::::::::::::::::;%$!`.`````.................................................``:%$!:::::::::::::::::::::::::::::::%!`
`||:::::::::::::::::::;|$!`..```.......................................................```;$%;::::::::::::::::::::::::::::%!`
!|:::::::::::::::::!$%'`.............................................................``..``'%&|;::::::::::::::::::::::::;%;.
;%;::::::::::::::!$!```..............................................................`...````'%@$|;:::::::::::::::::::::!%:.
'|!::::::::::::!$!`.`....................................................................``````'%&$$|:::::::::::::::::::||`.
.!|::::::::::;%! ..........................................................................````;&&$$%;::::::::::::::::%! .
:%;::::::::%%` ...````````.........`.............................................```.``.'%&$%$%!:::::::::::::;%; .
.!|::::::!%; . .....```..```````````.``........................................``!&$$%%%!:::::::::::!|' .
:|;::::|%' .. ....``..........................................:$&$$$$%;:::::::::%! .
!%::;%|'``..... .....```..................................................````:$&$$%$$|;::::::!%' .
'|!;%|`.......`.`.........````````..`.......```...........`````.................................````:%&$$$$$%!:::::%! .
;$$|`...`':'..`.`````....`````|!`````...................```.````.................`....````..........:$&$%%%%$|:::!|' .
.||``.``'|!```...........``.`:|;````;!'.``..............```.::```...................`'!:.`.......`..`;$&%%%$$$|;;%; .
;|'...``!|'``.`````..........;|:``.:$|`...................``;|:......................'|!```.......``.`!&$%%$%$$%$! .
:|:.``..'|!.``..``````......``!%:.`:%&|```...............```'!%|:````.`....```.......`'|!..............'%&$%$$$$@|. .
`|;..````:|:..``;|'.```.......`;%;`:%&#!```..................:|$%:``'|!``````.......```'|!``..........```;$&$%$$@|. .
!|``...``;|:`..'%%'..```..```:%&&!'!&&$!`.```.``..........```;%&%```|&;``:%!```....```.'|;.``...`.``..`.``|&$$$@| .
:|:.``````;|:``;$@%:````````'|$;:%%;%&!||`....`''........``..:|$&!``!&&&;``|#$'``....``.:|;`````..`!|'``..`:$&&&; .
!!````||``:|;`!$@#$:`....``:%|:::;$$$%`;|'....`:'...........`;%&%:`!$;:!&%'!$$&!`...```.;|'`..```..;$;....``|#&$; .
:|:..`:%;```||;%&@@&;``````;$!:'` .;&@; `|;````.::`........``:|%&!`|$;:` `|$$|;%@@|'....`||`````..``;$|'..```;%!||. .
|!.```!|'```;$%$&$&&|'`'|$$&|:'. `'. !|`..`.';'.........'!%&%;|%:'. '%@#&: `|&%:```:|;`````````;$%:```..'||!%: .
'|:```'%!`..``!&&&%$&%:`.`:%%|$@&!` `|!```.'!;`....``.`;|$&%%%:;|&$:. :&@%;`!|`.`````..`;$$;::`.``!%;%! .
!|`..`!$;..`..:&@$|%&&!'`'%%:` .;$@$:. :|:...`;|;`.`.`..:|%&@&&%:. .|&$&@$;.....`````;$$!!!'..`;%;!|` .
.|!`..:$%'```.`;||||%&@$;`!%;` '!!|%:.``;|!'```..'!%&#&;'. !&;````.......```;$$||!'..`:%!;%; .
`|;..`!&|````.:!||||%&&&%|%!'. :%;``;||;````'!|$@%:` `:|$@#####%` :$!``..``........;$%|||:`.`'||:%! .
'|:..:|&|`''``:|||||%&%'%@!.;@@@#####@&$|!'. `|!';|%!'```;%$&||&&@@@@@&&&&&@#| :$|'``.......``.`!$%|||;```'||:||` .
:|'.`;%&!.:;``;|||||%&%` `|@&&&&&&&&&&@&' ;&$%|!'.`;|$&;.!@&&&&&&&&&&&@#|. '%|'``.......````!&%||%!`.`'||:;%: .
:|'.`;%$!`;!'`;|||||%&|. '%|;%&&&&&&&&@$` !&$|:`;%&%` !%`.!&&&&&$$$$@%` '%|'``.```...````|&%|||!'.`'||:;%; .
:|'.'!%$!`;|:`;|||||%&|. :; `|%|%%|||$|. ;$|;$&; :: `!%%|%||||&%` '%%'``.```.''```'%$%|||!'.`'||::%! .
'|:`:|%$!`;|;`;|||||%&! ;$||||%|%%|||&; .'` '%|||||%%%||||&%. '%|'``...`.':`.`:%$|||||:..:|!::||. .
`!;.:|%&!`;||:;||||%$&; ;$||||||||||$%' .|$|||%%%%|||%@| '$|'.`..`.`:!:``!$%|||||:``;$!::!|` .
.||`:|%&|`;||;;||||%&%` '%%||%%%||%%&! :%|||%|||%||$$' :$!`..`````;|:``|&||||||:.`|&!::!|' .
`$%''!|&%';||||||||%&! !$|'.```:|&%. ;$%' :$&: ;$!`......:||:`:%$||||||:.:$$;::!%: .
'$&;'!|$$::|||||||%&%` .|&: .!@|. .|&|`.`;&$' !&;`....``;||;`!$%||||||:`!&%;::!%: .
:%$|';|%&!'!||||||%&%' ......`!@##@!. '|&&|'.`.... .|$:...```:|||;'%$|||||%$;:$&|;::!%: .
;%;%|;||&$::||||||%$$:..``````````. ;; ...````````..`|%'....`'!|||:;$%||||%$$!|&$|;::!%: .
;%;|$|!|%&|`;%|||||%&!..`````````... .|#################@@$;. ..``````````.:$|'```.`;||||;%$||%%%%&$%&$%|:::!|' .
:|;;%&$||%$;:$$||||%&%'..````````.. '$##&;``````````````:$&' ..```````.. ;$!`````:||||!%$%|$&$|$#@&$%%!:::||` .
'|!:|$@&%%$$;;&$||||%&|. ........ :@$:`````````````````|$: ...... !$:.```'!%%||%$%|%&@$$##@$%$%;:::|!. .
!%:!%$@&%%@@!%@%||||%&%` '$!``````````````````|%` `%%'``.'!%&&%$@$%%&#&@##@$%%$|;:::%! .
`%&&@$|!$&&$$#&&$%|||%&#%` .|$:````````````````:%: :$!````;|$&%%@&%$&%&@; `|@@&%;:::;|: .
'&&';!:%&%|||$&$$@$: .|&;``````````````;%: .;&@@$:`.`;|$@$$@&$&|'%%. .:|$&@|. .
`' ;&$||%&&%||%&@|` `%&!``````````:%!. `!&@$%%%&|`.`:|$@&&#@&$: .
!&$%%&#@%|||%$&@%' .';;'`...''. `!&#&%|||||%$$;`.:%&#@@#@@!. .
.;%&&$$&! :&&$&%|@$%%&@$%%$@#@|:. .`;%&@&@$:``:%&$%%%&@%``:%@#@||#|!$!'';|$@! .
;&%:```'|$: :$#%.`|@@@%!&#&;```':;|&#@@@@@@@&$%|!;:::|&!. '$%``|;`;&|. .;!|$;``'!%&@; .
.%&$$$%|;;$%` `%$!':%%` `|&|::::::::::;$%` ;&$!|%|&|. `%@$$&&&&@#%` .
`;;;;;;;;;;` || '$; :$|:::::'!&! `%|. !|` !|. .::. .
*/