June 2022 The Thirteenth Blue Bridge Cup Software Competition National Finals C++A Group Questions

Results and review

Estimated score : 0 + 0 + 10 + 10 + 2 + 15 + 10 + 8 + 10 + 0 = 65
Results : National second prize in the top

The author estimates his own score has always been very accurate, as for this competition:

  1. The estimated score will not be too high, because the programming questions are basically matched on the field
  2. The estimated score will not be low, and will not pretend to be weak

experience

The author is a retired ACM student. He has participated in three Blue Bridge Cup National Championships. The results are the 11th CB National 2nd, the 12th CA National 3rd, and the 13th CA National 2nd. Due to the lack of a little strength and luck, I didn't achieve much in the ACM competition, but I think I have some competition experience and experience. There are many places in the Blue Bridge Cup that are really not doing well, and they have to be scolded. It is undeniable that it provides many students who are not good enough (ACM regional competition) or have not participated in the algorithm competition (ACM provincial competition) A more popular and suitable competition platform has been established. For the Blue Bridge Cup, in order to achieve satisfactory results, I think the most important thing is to be careful. Although this word seems to be a catch-all phrase, it is especially important for the Blue Bridge Cup:

  • handle it seriously. This is the truth that the author only understands after suffering a lot. When you want to do something well, or when you will have regrets if you don’t do it well, you should do it with a humble attitude Ok this thing. For example, in the Blue Bridge Cup, I remember that the C/C++ group must return 0, which is clearly written in the entry manual, but there are still many students who make such low-level mistakes every year. In addition, this year is a new platform competition. In the programming question submission box, Ctrl+A is not a shortcut key. Many students modify the code without overwriting the previously submitted code (this is more of a platform problem). This can be avoided by taking a minute or two to simply check it out.

  • Compared with other competitions, carefulness is more important in the Blue Bridge Cup. For example, in the ACM competition and the weekly competition, there will be time penalties for wrong submissions. When participating in the ACM competition, the author and teammates also maintain a cautious attitude. Sometimes the code must be tested repeatedly before submitting, for fear of returning an error. However, if the ACM competition is wrong, you can continue to submit, but it takes more time (of course, it does not mean that time is not important. In many cases, the number of solutions is the same, and you need to spend less time to win the award), and the Blue Bridge Cup, once I made a low-level mistake (in this provincial competition, the author failed the entire question because of a wrong line of code in the frog question), and the result is likely to be that the whole question almost failed directly. A recommended solution: program matching , students who don’t know about matching can refer to the above articles or search online by themselves, so I won’t repeat them here. It was also the low-level mistakes in the provincial competition that made me firm up my determination to write matchmaking in the national competition. Therefore, although there were not many questions written in the national competition, they were basically guaranteed to be correct.

  • game strategy. 1. The difficulty of the topic does not guarantee a gradient increase. That is to say, the later questions may be simpler than the previous ones. If you encounter stuck questions, decisively choose to skip and change to other questions may be the key to victory. Second, there are partial scores. For example, the H question in this national competition replaces characters, and the violent solution gets 8 points. Isn’t it much simpler than the previous RMQ and the shortest path? The data range of a question directly determines the method of solving the question and the difficulty of the question. So in the last hour, make sure to get the small data points for all the questions, they are really simple.

Sincerely hope to help others

——2022.07.08


Question A: Little Blue and the Key

insert image description here

C(28,14)*staggered

Mismatches can be inclusive or recursive

1286583532342313400

code show as below:

#include <bits/stdc++.h>
using namespace std;

const int N = 16;
long long dp[N];
int main() {
    
    
    long long ans = 1;
    int ct = 2;
    for (int i = 15; i <= 28; i++) {
    
    
        ans = ans * i;
        while (ans % ct == 0 && ct <= 14)
            ans /= ct, ct++;
    }
    dp[2] = 1, dp[3] = 2;
    for (int i = 3; i <= 14; i++)
        dp[i] = 1ll * (i - 1) * (dp[i - 1] + dp[i - 2]);
    cout << ans * dp[14] << endl;
    return 0;
}

Question B: Permutation distance

insert image description here

Cantor expansion, pay attention to the circular arrangement.

Question C: Memory Space

insert image description here
insert image description here

Estimated score: 100%

Just simulate

code show as below:

#include <bits/stdc++.h>
using namespace std;

const int N = 1e5 + 5;
const long long mod = 1e9 + 7;
string str;

void solve()
{
    
    
	int n;
	scanf("%d", &n);
	getchar();
	long long ans = 0;
	for (int i = 1; i <= n; i++)
	{
    
    
		getline(cin, str);
		string TP = "";
		int m = str.size();
		bool f = 0;
		for (int i = 0; i < m; i++)
		{
    
    
			if (!f)
			{
    
    
				TP += str[i];
				if (TP == "int" || TP == "long" || TP == "String")
					f = 1;
				continue;
			}
			if (TP == "String")
			{
    
    
				bool flag = 0;
				for (int j = i; j < m; j++)
				{
    
    
					if (!flag)
					{
    
    
						if (str[j] == '\"')
							flag = 1;
						continue;
					}
					if (str[j] == '\"')
					{
    
    
						flag = 0;
						continue;
					}
					ans++;
				}
				break;
			}
			if (str[i] == '[')
			{
    
    
				bool flag = 0;
				long long res;
				for (int j = i + 2; j < m; j++)
				{
    
    
					if (!flag)
					{
    
    
						if (str[j] == '[')
							flag = 1, res = 0;
						continue;
					}
					if (str[j] == ']')
					{
    
    
						flag = 0;
						ans += res * (TP == "int" ? 4 : 8);
						continue;
					}
					res = res * 10 + str[j] - '0';
				}
				break;
			}

			for (int j = i; j < m; j++)
			{
    
    
				if (str[j] == ',' || str[j] == ';')
					ans += (TP == "int" ? 4 : 8);
			}
			break;
		}
	}
	long long B = ans % 1024;
	long long KB = ans / 1024 % 1024;
	long long MB = ans / 1024 / 1024 % 1024;
	long long GB = ans / 1024 / 1024 / 1024 % 1024;
	if (GB)
		printf("%lldGB", GB);
	if (MB)
		printf("%lldMB", MB);
	if (KB)
		printf("%lldKB", KB);
	if (B)
		printf("%lldB\n", B);
}
int main()
{
    
    
	solve();
	return 0;
}
/*
1
long[] nums=new long[131072];

4
int a=0,b=0;
long x=0,y=0;
String s1=?? hello??,s2=??world??;
long[] arr1=new long[100000],arr2=new long[100000];
*/

Question D: Greatest Common Divisor

insert image description here

Estimated score: 100%

If there is already 1 1 in the array1 , then directly use1 11 can be tiled.

Otherwise, find the minimum interval that satisfies the interval GCD = 1 GCD=1GCD=1 , use this1 11 for tiling.

You can use dichotomy + RMQ to find the method.

code show as below:

#include <bits/stdc++.h>
using namespace std;

const int N = 1e5 + 5;
const long long mod = 1e9 + 7;
const long long INF = 0x3f3f3f3f;
int a[N];

struct node
{
    
    
	int l, r, g;
} tr[N << 2];

void pushup(int k)
{
    
    
	tr[k].g = __gcd(tr[k * 2].g, tr[k * 2 + 1].g);
}

void build(int k, int l, int r)
{
    
    
	tr[k].l = l, tr[k].r = r;
	if (l == r)
	{
    
    
		tr[k].g = a[l];
		return;
	}
	int mid = l + r >> 1;
	build(k * 2, l, mid);
	build(k * 2 + 1, mid + 1, r);
	pushup(k);
}

int query(int k, int L, int R)
{
    
    
	if (tr[k].l == L && tr[k].r == R)
	{
    
    
		return tr[k].g;
	}
	int mid = (tr[k].l + tr[k].r) >> 1;
	if (R <= mid)
		return query(k * 2, L, R);
	else if (L > mid)
		return query(k * 2 + 1, L, R);
	else
		return __gcd(query(k * 2, L, mid), query(k * 2 + 1, mid + 1, R));
}

void solve()
{
    
    
	int n;
	scanf("%d", &n);
	int ct = 0;
	for (int i = 1; i <= n; i++)
	{
    
    
		scanf("%d", &a[i]);
		ct += a[i] == 1;
	}
	if (ct) //有1直接平铺
	{
    
    
		printf("%d\n", n - ct);
		return;
	}
	build(1, 1, n);
	if (query(1, 1, n) != 1) //肯定不行
	{
    
    
		puts("-1");
		return;
	}

	int min_step = INF;
	for (int i = 1; i <= n; i++)
	{
    
    
		int l = i + 1, r = n, res = INF;
		while (l <= r)
		{
    
    
			int mid = l + r >> 1;
			if (query(1, i, mid) == 1)
			{
    
    
				res = mid - i;
				r = mid - 1;
			}
			else
				l = mid + 1;
		}
		min_step = min(min_step, res);
	}
	printf("%d\n", min_step + n - 1);
}
int main()
{
    
    
	solve();
	return 0;
}
/*
3
4 6 9

5
6 4 6 10 5
*/

Question E: owo

insert image description here

Estimated score: 10%

It should be a DP. I didn't have any ideas at the beginning, and I didn't have time to think about it later, so I handed in violence.

code show as below:

#include <bits/stdc++.h>
using namespace std;

const int N = 1e6 + 5;

int ans = 0;
string s[N];

int ct = 0;
int func()
{
    
    
	int r = 0;
	for (int i = 1; i <= 1e3; i++)
	{
    
    
		random_shuffle(s + 1, s + 1 + ct);
		string tmp;
		for (int i = 1; i <= ct; i++)
			tmp += s[i];
		int n = tmp.size();
		int res = 0;
		for (int i = 2; i < n; i++)
			res += tmp[i - 2] == 'o' && tmp[i - 1] == 'w' && tmp[i] == 'o';
		r = max(r, res);
	}
	return r;
}
void solve()
{
    
    
	srand(time(NULL));
	int n;
	cin >> n;
	for (int i = 1; i <= n; i++)
	{
    
    
		string str;
		cin >> str;
		if (str[0] != 'o' && str[0] != 'w' && str[(int)str.size() - 1] != 'o' && str[(int)str.size() - 1] != 'w') //剪枝
		{
    
    
			printf("%d\n", ans);
			continue;
		}
		else
		{
    
    
			s[++ct] = str;
			ans = func();
			printf("%d\n", ans);
		}
	}
}
int main()
{
    
    
	solve();
	return 0;
}

Question F: Environmental Governance

insert image description here
insert image description here

Estimated score: 100%

A relatively simple question, two points + FLOYD to find the shortest path. Time complexity n 3 logmn^3logmn3 logm, where m is the number of days required to clear all paths to the lower limit (open1 e 8 , 1 e 9 1e8, 1e91e8 , 1e9 will work ) . _

code show as below:

#include<bits/stdc++.h>
using namespace std;

const int N = 105;
const long long mod = 1e9+7;
const int INF= 0x3f3f3f3f;

int w[N][N];
int ww[N][N];
int minn[N][N];
int n , q;
int check(int day)
{
    
    
	int ans =0 ;
	for(int i =0; i<n; i++)
		for(int j =0; j<n; j++)
			ww[i][j]=w[i][j];

	for(int i =0; i<n; i++)
	{
    
    
		int val = day/n+(day%n>=i+1?1:0);
		for(int j =0 ; j<n; j++)
			ww[i][j]-=val,ww[j][i]-=val;
	}

	for(int i =0; i<n; i++)
		for(int j =0 ; j<n; j++)
			ww[i][j]=max(minn[i][j],ww[i][j]);

	for(int k =0 ; k<n; k++)
		for(int i =0 ; i<n; i++)
			for(int j =0 ; j<n; j++)
				ww[i][j]=min(ww[i][j],ww[i][k]+ww[k][j]);
	for(int i =0; i<n; i++)
		for(int j =0; j<n; j++)
			ans+=ww[i][j];
	return ans ;
}


void solve()
{
    
    
	scanf("%d %d",&n,&q);
	for(int i =0; i<n; i++)
		for(int j =0 ; j<n; j++)
			scanf("%d",&w[i][j]);
	for(int i =0; i<n; i++)
		for(int j =0 ; j<n; j++)
			scanf("%d",&minn[i][j]);
	int  l =0,r= 100000*n,ans =-1;
	while(l<=r)
	{
    
    
		int mid = l+r>>1;
		if(check(mid)<=q)
		{
    
    
			r= mid -1;
			ans = mid;
		}
		else
			l=mid+1;
	}
	cout<<ans<<endl;
}
int main()
{
    
    
	solve();
	return 0;
}

Test Question G: Selecting Prime Numbers

insert image description here

Estimated score: 30%

Mathematics waste, no ideas, and violence.

code show as below:

#include <bits/stdc++.h>
using namespace std;

const int N = 5005;
const long long mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;

bool f[N];
int prime[N];
int ct;

void init()
{
    
    
	f[0] = f[1] = 1;
	for (int i = 2; i < N; i++)
		if (!f[i])
		{
    
    
			prime[++ct] = i;
			for (int j = i + i; j < N; j += i)
				f[j] = 1;
		}
}
void solve()
{
    
    
	init();
	int n;
	cin >> n;
	for (int x = 2; x <= n; x++)
	{
    
    
		for (int p1 = 1; p1 <= ct && prime[p1] < x; p1++)
		{
    
    
			int xx = x;
			int a = prime[p1];
			if (x % a)
				xx = (xx / a + 1) * a;
			if (xx > n) //剪枝
				continue;
			for (int p2 = 1; p2 <= ct && prime[p2] < xx; p2++)
			{
    
    
				a = prime[p2];
				int xxx = xx;
				if (xx % a)
					xxx = (xx / a + 1) * a;
				if (xxx == n)
				{
    
    
					cout << x << endl;
					return;
				}
			}
		}
	}
	puts("-1");
}
int main()
{
    
    
	solve();
	return 0;
}

Question H: Substitution Characters

insert image description here

Estimated score: 40%

It feels like a magical data structure is needed to maintain, but no, violence is handed over.

#include <bits/stdc++.h>
using namespace std;

const int N = 1e5 + 5;
const long long mod = 1e9 + 7;
const long long INF = 0x3f3f3f3f;
char s[N];
int l, r;
char a[3], b[3];

void solve()
{
    
    
	scanf("%s", s + 1);
	int n = strlen(s + 1);
	int m;
	scanf("%d", &m);
	while (m--)
	{
    
    
		scanf("%d %d %s %s", &l, &r, a, b);
		for (int i = l; i <= r; i++)
			if (s[i] == a[0])
				s[i] = b[0];
	}
	printf("%s", s + 1);
}
int main()
{
    
    
	solve();
	return 0;
}

Question I: Triangular Sequence

insert image description here

Estimated score: 40%

Each triangle is maintained separately, similar to the idea of ​​​​blocking, and the boundaries are maintained separately.

Time complexity: nmlognlogn nmlognlognnmlognlogn

code show as below:

#include <bits/stdc++.h>
using namespace std;

const int N = 2e5 + 5;
const long long mod = 1e9 + 7;
const long long INF = 0x3f3f3f3f;

struct tri
{
    
    
	int typ, len, l, r;
} a[N];
long long pre[N]; //前缀列数量之和
int n, m;
long long cal2(int len, int h) //计算边长为len的三角形 高度<=h的贡献
{
    
    
	long long sum = 1ll * len * (len + 1) / 2;
	long long len2 = max(0, len - h);
	long long res = 1ll * len2 * (len2 + 1) / 2;
	return sum - res;
}
long long cal(int col, int idx, int h) //计算 第idx个三角形,从第col列开始, 高度<=h的贡献
{
    
    
	if (col > a[idx].r)
		return 0;
	if (a[idx].typ == 0)
	{
    
    
		long long s1 = cal2(a[idx].len, h);
		long long len2 = col - a[idx].l;
		long long s2 = cal2(len2, h);
		return s1 - s2;
	}
	else
	{
    
    
		long long len2 = a[idx].r - col + 1;
		return cal2(len2, h);
	}
}
int check(int l, int r, int h)
{
    
    
	int left_idx = lower_bound(pre + 1, pre + 1 + n, l) - pre;
	int right_idx = lower_bound(pre + 1, pre + 1 + n, r) - pre;
	if (left_idx == right_idx) //只有一个三角形
		return cal(l, left_idx, h) - cal(r + 1, left_idx, h);
	else
	{
    
    
		long long ans = 0;
		ans += cal(l, left_idx, h);
		ans += cal(a[right_idx].l, right_idx, h) - cal(r + 1, right_idx, h);
		for (int i = left_idx + 1; i < right_idx; i++) //计算中间的三角形贡献
			ans += cal(a[i].l, i, h);
		return ans;
	}
}

void solve()
{
    
    

	scanf("%d %d", &n, &m);
	int max_h = 0;
	for (int i = 1; i <= n; i++)
	{
    
    
		scanf("%d %d", &a[i].len, &a[i].typ);
		pre[i] = pre[i - 1] + a[i].len;
		a[i].l = pre[i - 1] + 1;
		a[i].r = pre[i];
		max_h = max(max_h, a[i].len);
	}

	for (int i = 1; i <= m; i++)
	{
    
    
		int L, R, v;
		scanf("%d %d %d", &L, &R, &v);
		int l = 1, r = max_h, h = -1;
		while (l <= r)
		{
    
    
			int mid = l + r >> 1;
			if (check(L, R, mid) >= v)
			{
    
    
				h = mid;
				r = mid - 1;
			}
			else
				l = mid + 1;
		}
		printf("%d\n", h);
	}
}
int main()
{
    
    
	solve();
	return 0;
}

Exam J: Bracket sequence tree

insert image description here

Definition of maximum matching for a tree?

Guess you like

Origin blog.csdn.net/hesorchen/article/details/125345898