「赛后总结」20221024 CSP 模拟赛

「赛后总结」20221024 CSP 模拟赛

点击查看目录

赛时

又垫底了。

光速过掉了 T1,光速过掉了 T2。

开始刚 T3,推出了式子,但想了半天不知道怎么 \(\Theta(1)\)\(\Theta(\log_2n)\) 求出。

于是开始刚 T4,发现就是一个最长路。

写了一半 SPFA 发现需要高精,于是继续刚 T3。

感觉能拿一些可观的部分分,于是写了一份 \(\Theta(n)\) 代码。

然后突然发现 \(\Theta(n)\) 就是可以过的……

写完后继续写 T4,然后突然想起老吕说过:“宁可争第二第三也不要争第一,第一肯定有问题”。

然后我觉得 xuany 和 Rolling_Star 中肯定有一个能 AK。

于是我就放水摆烂不写高精,拿了 \(\text{30pts}\),控到了 \(\text{rank2}\)

2023/03/31:其实就是菜

赛后:

\[\text{330pts}+\text{4h}=\!\triangleq \!=\text{400pts}\uparrow \]

题解

T1

思路

翻转,判断,输出,没了。

代码

点击查看代码
namespace SOLVE {
	typedef long double ldb;
	typedef long long ll;
	typedef double db;
	const ll N = 1e6 + 10;
	ll n;char s[N], t[N];
	inline ll rnt () {
		ll x = 0, w = 1; char c = getchar ();
		while (!isdigit (c)) { if (c == '-') w = -1; c = getchar (); }
		while (isdigit (c)) x = (x << 3) + (x << 1) + (c ^ 48), c = getchar ();
		return x * w;
	}
	inline void In () {
		scanf ("%s", s + 1);
		scanf ("%s", t + 1);
		n = strlen (s + 1);
		return;
	}
	inline void Solve () {
		_for (i, 1, n / 2) std::swap (t[i], t[n - i + 1]);
		return;
	}
	inline void Out () {
		_for (i, 1, n) if (s[i] == '#') putchar (t[i]);
		puts ("");
		return;
	}
}

T2

思路

双指针直接淦。

没了。

代码

点击查看代码
namespace SOLVE {
	typedef long double ldb;
	typedef long long ll;
	typedef double db;
	const ll N = 1e7 + 10, inf = 1e12;
	ll n, a, b, flower[N], left, right, cnt[3], ans = inf;
	inline ll rnt () {
		ll x = 0, w = 1; char c = getchar ();
		while (!isdigit (c)) { if (c == '-') w = -1; c = getchar (); }
		while (isdigit (c)) x = (x << 3) + (x << 1) + (c ^ 48), c = getchar ();
		return x * w;
	}
	inline void In () {
		n = rnt (), a = rnt (), b = rnt ();
		_for (i, 1, n) flower[i] = rnt ();
		return;
	}
	inline void Solve () {
		left = 1;
		_for (i, 1, n) {
			++cnt[flower[++right]];
			while (1) {
				if (left > right) break;
				if (flower[left] == 1 && cnt[1] <= a) break;
				if (flower[left] == 2 && cnt[2] <= b) break;
				--cnt[flower[left++]];
			}
			if (cnt[1] >= a && cnt[2] >= b) ans = std::min (ans, cnt[0]);
		}
		return;
	}
	inline void Out () {
		printf ("%lld\n", ans);
		return;
	}
}

T3

思路

观察可以发现,每个点 \((x,y)\) 会被影响 \((x1-x+1)(y1-y+1)\) 次。

把头旋转 \(180^\circ\) 度可以发现,这个式子可以写成 \(xy\)

显然如果这个点亮时,\(xy\) 为奇数,即 \(x,y\) 均为奇数。

当矩形中这种点的数量为 \(k\) 时,该矩阵合法。

那么答案为:

\[\large\sum_{\left\lfloor\frac{x+1}{2}\right\rfloor*\left\lfloor\frac{y+1}{2}\right\rfloor=k}(n-x+1)(m-y+1)\\ \]

可以发现我们枚举 \(x\) 即可求出相应的 \(y\),可以 \(\Theta(n)\) 解决。

代码

点击查看代码
namespace SOLVE {
	typedef long double ldb;
	typedef long long ll;
	typedef double db;
	const ll N = 1e5 + 10, P = 998244353;
	ll n, m, k, ans;
	inline ll rnt () {
		ll x = 0, w = 1; char c = getchar ();
		while (!isdigit (c)) { if (c == '-') w = -1; c = getchar (); }
		while (isdigit (c)) x = (x << 3) + (x << 1) + (c ^ 48), c = getchar ();
		return x * w;
	}
	inline void In () {
		n = rnt (), m = rnt (), k = rnt ();
		return;
	}
	inline void Solve () {
		_for (i, 1, n) {
			ll x = (i + 1) / 2;
			if (k % x) continue;
			ll y = k / x * 2;
			if (y <= m) ans = (ans + (n - i + 1) * (m - y + 1) % P) % P;
			if (y <= m + 1) ans = (ans + (n - i + 1) * (m - y + 2) % P) % P;
		}
		return;
	}
	inline void Out () {
		printf ("%lld\n", ans);
		return;
	}
}

T4

思路

首先求出 \(1\) 坎特币最多能换多少其他货币,这个可以直接用我们伟大的敬爱的可爱的精巧的强大的深刻的正确的一针见血的跑得飞快的我编不下去了的 SPFA 算法跑最长路解决。

这里有个小技巧:乘的运算过于复杂时可以直接取对数来转换成加法,本题明给出了 \(10^z\),可以直接指数相加。

跑完 SPFA 后需要算出总共需要多少坎特币,这里无法避免高精,直接 像我一样4h 即可。

代码

点击查看代码
namespace SOLVE {
	typedef long double ldb;
	typedef long long ll;
	typedef double db;
	const ll N = 1e5 + 10;
	ll n, m, need[N], dis[N], jl[N];
	class Graph {
	public:
		ll v, w;
		inline bool operator < (Graph another) {
			return w < another.w;
		}
	};
	std::vector <Graph> tu[N];
	class BigNum {
	public:
		ll len = 20, a[N];
		inline void Print () {
			for_ (i, len, 20) printf ("%lld", a[i]);
			// for (ll i = len; i >= 20; --i) printf ("%lld", a[i]);
			putchar ('.');
			for_ (i, 19, 14) printf ("%lld", a[i]);
			return;
		}
	} ans;
	inline ll Cnt (ll num) {
		ll cnt = 0;
		while (num) ++cnt, num /= 10;
		return cnt;
	}
	inline ll rnt () {
		ll x = 0, w = 1; char c = getchar ();
		while (!isdigit (c)) { if (c == '-') w = -1; c = getchar (); }
		while (isdigit (c)) x = (x << 3) + (x << 1) + (c ^ 48), c = getchar ();
		return x * w;
	}
	inline void SPFA () { // I love SPFA! I hate Dijkstra!
		std::queue <ll> q;
		memset (dis, 0x3f, sizeof (dis));
		q.push (1), jl[1] = 1, dis[1] = 0;
		while (!q.empty ()) {
			ll u = q.front (); q.pop (), jl[u] = 0;
			far (v, tu[u]) {
				if (dis[v.v] > dis[u] + v.w) {
					dis[v.v] = dis[u] + v.w;
					if (!jl[v.v]) q.push (v.v);
				}
			}
		}
		return;
	}
	inline void In () {
		n = rnt (), m = rnt ();
		_for (i, 1, n) need[i] = rnt ();
		_for (i, 1, m) {
			ll u, v, w;
			u = rnt (), v = rnt (), w = -rnt ();
			tu[u].push_back (Graph { v, w });
		}
		return;
	}
	inline void Solve () {
		SPFA ();
		_for (i, 1, n) {
			ll k = dis[i] + 20;
			if (dis[i] < -15) continue;
			ans.len = std::max (ans.len, k);
			ans.a[k] += need[i];
			while (ans.a[k] > 10) {
				ans.a[k + 1] += ans.a[k] / 10;
				ans.a[k] %= 10;
				while (ans.a[ans.len + 1]) ++ans.len;
			}
		}
		return;
	}
	inline void Out () {
		_for (i, 5, ans.len) {
			ans.a[i + 1] += ans.a[i] / 10;
			ans.a[i] %= 10;
			if (ans.a[ans.len + 1]) ++ans.len;
		}
		if (ans.a[13] > 4) ++ans.a[14];
		ans.Print ();
		return;
	}
}
posted @ 2022-10-24 19:40  K8He  阅读(52)  评论(7编辑  收藏  举报