5.2 模拟赛总结

这两天的模拟赛,可以明显地反映出我的弱点——学过的知识点容易忘,即理解差。

所以,我决定将每次模拟赛的知识点先找出,以便我做题。这可能是个好习惯。

30 / 400 30 / 400 30/400

A

Chess Queen

0 / 100 0/100 0/100

很明显,这是一道数学题。

先考虑两个皇后在一行,或者一列。比较好像,一行的时候是 n m ( n − 1 ) nm(n-1) nm(n1),一列的时候是 n m ( m − 1 ) nm(m-1) nm(m1)

难推出的是同一斜线上的情况 (没想推,然后废了)。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

就像这个图,是一个 4 × 5 4\times5 4×5 的矩形,有三种斜线,各两条,并且反过来也各有两条。

所以, 2 × [ A 2 2 + A 3 2 + . . . . . . + A n 2 × ( m − n + 1 ) + A 3 2 + A 2 2 ] 2\times[A^2_2+A^2_3+......+A^2_n\times(m-n+1)+A^2_3+A^2_2] 2×[A22+A32+......+An2×(mn+1)+A32+A22]

然后可以化简为 2 ( 3 m − n − 1 ) ( n − 1 ) n 3 \dfrac{2(3m-n-1)(n-1)n}{3} 32(3mn1)(n1)n

将上面说到的三种情况加起来就是最终的方案数了。

#include <bits/stdc++.h>

using namespace std;

unsigned long long n, m;

signed main() {
	ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
	while (cin >> n >> m) {
		if (n == 0 && m == 0) return 0;
		if (n > m) swap(n, m);
		cout << n * m * (n + m - 2) + 2 * (3 * m - n - 1) * (n - 1) * n / 3 << '\n';
	}
}

B

ARC175B Parenthesis Arrangement

5 / 100 5/100 5/100

我认为最难的一道。

B × 2 ≥ A B\times2\ge A B×2A 那么用操作一。

否则用操作二。

#include <bits/stdc++.h>
#define int long long

using namespace std;
const int maxn = 5e5 + 10;

int n, a, b;
string s;
int l, r, m;

signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	cin >> n >> a >> b >> s;
	for (int i = 0; i < 2 * n; ++i) {
		if (s[i] == ')') {
			if (m) m--;
			else l++, m++;
		}
		else m++;
	}
	if (n) r = m / 2;
	if (l < r) swap(l, r);
	if (b * 2 <= a) cout << (l + r) * b;
	else cout << r * a + (l - r) * b;
}

C

ABC348D Medicines on Grid

15 / 100 15/100 15/100

甚至,我这道题刷过。然后考场打废了。

一个 b f s bfs bfs 直接搞定了,记录药水的价值,在更新时取最小值。说实话,它就是 s p f a spfa spfa

#include <bits/stdc++.h>
using namespace std;
const int maxn = 2e2 + 10;

struct node {int x, y, e;};

int n, m, q;
int sx, sy, ex, ey;
int me[maxn][maxn];
bool g[maxn][maxn], vis[maxn][maxn];
int dis[maxn][maxn];
int dir[5][2] = {{0, 0}, {1, 0}, {0, 1}, {0, -1}, {-1, 0}};

void bfs() {
	vis[sx][sy] = 1;
	queue<node> q;
	q.push({sx, sy, 0});
	while(!q.empty()) {
		int x = q.front().x, y = q.front().y, e = q.front().e;
		q.pop();
		if(x == ex && y == ey) {cout << "Yes" << '\n';return;}
		if(me[x][y] > 0 && e < me[x][y]) e = me[x][y];
		for(int i = 1; i <= 4; i++) {
			int nx = x + dir[i][0], ny = y + dir[i][1];
			if(vis[nx][ny] == 0 || e - 1 > dis[nx][ny]) {
				if(g[nx][ny] && e > 0) {
					dis[nx][ny] = e - 1;
					vis[nx][ny] = 1;
					q.push({nx, ny, e - 1});
				}
			}
		}
	}
	cout << "No\n";
}

int main() {
	ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
	char c;
	cin >> n >> m;
	for(int i = 1; i <= n; i++) {
		for(int j = 1; j <= m; j++) {
			cin >> c;
			if (c == '#') continue;
			g[i][j] = 1;
			if(c == 'S') sx = i, sy = j;
			else if(c == 'T') ex = i, ey = j;
		}
	}
	cin >> q;
	for(int i = 1, x, y, w; i <= q; i++) {
		cin >> x >> y >> w;
		me[x][y] = w;
	}
	bfs();
	return 0;
}

D

Walk Through the Forest

10 / 100 10/100 10/100

很简单的最短路加 d f s dfs dfs 求数量。

d f s dfs dfs 部分原来写错了。对于 d i s a > d i s b dis_a > dis_b disa>disb 的情况连一条边,然后 d f s dfs dfs 找到去终点有多少条路即可。

// 最短路计数 luogu yc
#include <bits/stdc++.h>
#define int long long

using namespace std;
const int maxn = 5e3 + 10, inf = 0x7f7f7f7f, mod = 100003;

int n, m;
struct node {
	int v, w;
};
vector<node> e[maxn << 1];

struct edge{
	int to, dis;
	bool operator < (const edge &o) const{return dis > o.dis;}
};

int dis[maxn];
bool vis[maxn];

void dijkstra(int s) {
	memset(vis, 0, sizeof vis);
	memset(dis, 0x7f, sizeof dis);
	priority_queue<edge> q;
	q.push({s, 0});
	dis[s] = 0;
	while (!q.empty()) {
		int u = q.top().to;
		q.pop();
		if (vis[u]) continue;
		vis[u] = 1;
		for (auto ed: e[u]) {
			int v = ed.v, w = ed.w;
			if (dis[v] > dis[u] + w) {
				dis[v] = dis[u] + w;
				q.push({v, dis[v]});
			}
		}
	}
}

int ans;

void dfs(int u, int fa) {
	if (u == 2) {
		ans++;
		return;
	}
	for (auto ed: e[u]) if (ed.v != fa) {
		if (dis[ed.v] < dis[u]) dfs(ed.v, u);
	}
}

void init() {
	for (int i = 0; i < maxn; ++i) e[i].clear();
	ans = 0;
}

void solve() {
	init();
	for (int i = 1, u, v, w; i <= m; ++i) {
		cin >> u >> v >> w;
		e[u].push_back({v, w});
		e[v].push_back({u, w});
	}
	dijkstra(2);
	if (dis[2] == inf) {
		cout << 0 << '\n';
		return;
	}
	dfs(1, 0);
	cout << ans << '\n';
}

signed main() {
	ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
	while (cin >> n) {
		if (n == 0) exit(0);
		cin >> m;
		solve();
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值