第十五屆藍橋杯C++B組省賽總結

高明y發表於2024-04-14

A 握手問題

簡單模擬,答案為:1204 5pts

B 小球反彈

數學,最重要的一點,不考慮反彈,一直讓小球走,直到達到一個頂點,它就會反彈回去。
所以問題就變成了擴充套件這些方塊,直到滿足小球的角度,讓小球能達到另一個頂點。
\(233333 \times 15 a= 343720 \times 17b\)
解出來 a 和 b就知道我們要延長多少塊了,這裡需要約分,建議使用最大公約數求一下,然後直接用勾股定理,這裡用excel很好求。
答案:1100325199.77 5pts

C 好數

暴力可過,時間複雜度 \(O(7\times10^7)\) 10pts

int check(int x)
{
	int cnt = 1;
	while (x)
	{
		int p = x % 10;
		if (cnt % 2) 
		{
			if (p % 2 == 0) return false;
		}
		else 
		{
			if (p % 2 == 1) return false;
		}
		x /= 10;
		cnt++;
	}
	return true;
}

void solve()
{
	cin >> n;	
	int res = 0;
	for (int i = 1; i <= n; i++)
		if (check(i)) res++;
	cout << res;
}

D R格式

高精度+快速冪,但是沒必要,5分而已 5pts

// 5分程式碼
long long n;
double p;
void solve()
{
	cin >> n >> p;
	double res = p * pow(2, n);
	cout << (long long)(res + 0.5);
}

E 寶石組合

好像是分解質因數,比賽時看不出來,直接暴力3迴圈拿30% 4.5pts
這裡的公式可以化簡,化簡後就沒有最小公倍數了,只有最大公約數。

const int N = 100010;
int a[N];
int n;

int gcd(int a, int b)
{
	return b ? gcd(b, a % b) : a;
}

int calc(int a, int b, int c)
{
	return gcd(a, c) * gcd(b, c) / gcd(a * b / gcd(a, b), c);
}

void solve()
{
	cin >> n;
	for (int i = 1; i <= n; i++) cin >> a[i];
	sort(a + 1, a + 1 + n);
	
	int res = 0;
	int maxa, maxb, maxc;
	for (int i = 1; i <= n - 2; i++)
		for (int j = i + 1; j <= n - 1; j++)
			for (int k = i + 2; k <= n; k++)
			{
				if (res < calc(a[i], a[j], a[k]) && i != j && j != k && i != k)
				{
					maxa = a[i];
					maxb = a[j];
					maxc = a[k];
					res = calc(a[i], a[j], a[k]);
				}
			}
	cout << maxa << ' ' << maxb << ' ' << maxc;
}

F 數字接龍

看資料範圍,一眼暴力dfs
dfs的條件很多,很多細節,比賽時寫的程式碼在民間測試只過了60%不知道哪裡錯了 8pts

const int N = 15;

int g[N][N], dist[N][N];
bool st[N][N];
int n, k;

int dx[8] = {-1, -1, 0, 1, 1, 1, 0, -1};
int dy[8] = {0, 1, 1, 1, 0, -1, -1, -1};

bool dfs(int x, int y, int op, int cnt)
{
	if (x == n && y == n && cnt == n * n)
	{
		return true;
	}
	
	for (int i = 0; i < 8; i++)
	{
		int a = dx[i] + x, b = dy[i] + y, c = (op + 1) % k;
		if (a < 1 || a > n || b < 1 || b > n) continue;
		if (st[a][b]) continue;
		if (g[a][b] != c) continue;
		if (a + b < x + y) continue;
		
		st[a][b] = true;
		dist[x][y] = i;
		if (dfs(a, b, c, cnt + 1)) return true;
		st[a][b] = false;
	}
	return false;
}

void solve()
{
	cin >> n >> k;
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= n; j++)
			cin >> g[i][j];
	
	st[1][1] = true;
	if (!dfs(1, 1, 0, 1))
	{
		cout << -1 << endl;
		return;
	}
	
	int i = 1, j = 1;
	while (!(i == n && j == n))
	{
		int p = dist[i][j];
		cout << p;
		i = i + dx[p];
		j = j + dy[p];
	}
}

G 爬山

聽說是錯題,我用的優先佇列在民間資料上測試AC了 20pts

priority_queue<int> heap;
int n, p, q;
void solve()
{
	cin >> n >> p >> q;
	while (n--)
	{
		int x;
		cin >> x;
		heap.push(x);
	}
	while (p --)
	{
		int t = heap.top();
		heap.pop();
		t = sqrt(t);
		heap.push(t);
	}
	while (q--)
	{
		int t = heap.top();
		heap.pop();
		t /= 2;
		heap.push(t);
	}
	int res = 0;
	while (heap.size())
	{
		res += heap.top();
		heap.pop();
	}
	cout << res;
}

H 拔河

看錯題了,以為是人必須選完,但是可以有人不選的 0pts

相關文章