10.08模拟赛总结

总结

考场估分:\([50, 100] + [30, 50] + [0, 50] + [0, 5] = [80, 205]\)

实际得分:\(75+30+50+5=160\),寄,Rank 3。

upd:啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊!T1 开了 __int128 就 Rank 1 了,\(\text{185pts}\),凑。

\(\texttt{A}\)

标题没写错,文件名就是 \(\texttt{A}\)……

题意

给定一个 \(k\),求最小的 \(n\) 使得 \(k \mid n^2\) 并且 \(n \nmid k\)

分析

我用了一种很骚的写法……

枚举 \(n^2\)\(k\) 的几倍,然后由于 \(n\) 不是 \(k\) 的倍数,所以最多枚举到 \(k-1\),但是肯定超时,于是……双核处理一下(???),就是枚举 \(1, \ldots, \sqrt k\),分别处理一下 \(i \times k\)\(\dfrac{k^2}{i}\),随后便轻松愉快的使用 \(O(\sqrt k)\) 的时间复杂度 AC 了这道题。

警告:long long 会爆,要开 __int128,不然会 WA 75pts

考场寄因

挂分:25pts

原因:没开 __int128,爆 long long 了。

代码

点击查看代码
#include <bits/stdc++.h>

#define int __int128
#define IOS                \
	ios::sync_with_stdio(0); \
	cin.tie(0), cout.tie(0)

using namespace std;

int k;
int minn = 0x3f3f3f3f3f3f3f3f;

int read() {
	int x = 0, f = 1;
	char ch = getchar();
	while (ch < '0' || ch > '9') {
		if (ch == '-') {
			f = -1;
		}
		ch = getchar();
	}
	while (ch >= '0' && ch <= '9') {
		x = (x << 1) + (x << 3) + ch - '0';
		ch = getchar();
	}
	return x * f;
}

void put(int x) {
	if (x < 0) {
		putchar('-');
		put(-x);
		return;
	}
	if (!x) {
		return;
	}
	put(x / 10);
	putchar(x % 10 + '0');
}

signed main() {
	IOS;
	k = read();
	for (int i = 1; i * i <= k; i++) {
		int sq = sqrt((double)i * k);
		if ((sq * sq == i * k)) {
			minn = min(minn, sq);
		}
		int sq_ = sqrt((double)(k / i) * k);
		if ((k % i == (__int128)0) && (i != (__int128)1) && (sq_ * sq_ == (k / i) * k)) {
			minn = min(minn, sq_);
		}
	}
	put(minn == 0x3f3f3f3f3f3f3f3f ? (__int128) - 1 : minn);
	return 0;
}

\(\texttt{B}\)

题意

给定一个 \(n\) 个元素的序列 \(a\),如果 \(\gcd(a_i, a_{i + 1}) = 1\),那么可以交换 \(a_i\)\(a_{i + 1}\),求可以出现的不同序列数(原序列也算)。

分析

统计一下每个数字出现的次数,没了。

考场寄因

挂分:\(\text{0pts}\)

原因:没挂。

代码

点击查看代码
#include<bits/stdc++.h>
using namespace std;

const int kN = 1e5 + 5, p = 998244353;

int n, a[kN], cnts[12];
long long bs[kN], ibs[kN];
vector<pair<int, int>> blc;

int qpow(long long x, int y) {
	int ret = 1;
	while (y) {
		if (y & 1) ret = ret * x % p;
		x = x * x % p;
		y >>= 1;
	}
	return ret;
}

signed main() {
	ios::sync_with_stdio(0);
	cin.tie(0), cout.tie(0);
	cin >> n;
	blc.push_back({0, 0});
	for (int i = 1; i <= n; i++) {
		cin >> a[i];
		cnts[a[i]]++;
		if (a[i] == 6) {
			blc.push_back({0, 0});
		} else if (a[i] % 2 == 0) {
			blc.back().first++;
		} else if (a[i] % 3 == 0) {
			blc.back().second++;
		}
	}
	bs[0] = ibs[0] = 1ll;
	for (int i = 1; i <= n; i++) {
		bs[i] = bs[i - 1] * i % p;
	}
	ibs[n] = qpow(bs[n], p - 2);
	for (int i = n - 1; i >= 1; i--) {
		ibs[i] = ibs[i + 1] * (i + 1) % p;
	}
	long long ans = bs[n] * ibs[n - cnts[1] - cnts[5] - cnts[7]] % p;
	for (auto v : blc) {
		ans = ans * bs[v.first + v.second] % p * ibs[v.first] % p * ibs[v.second] % p;
	}
	ans = ans * ibs[cnts[1]] % p * ibs[cnts[5]] % p * ibs[cnts[7]] % p;
	cout << ans;
	return 0;
}

\(\texttt{C}\)

题意

给定一个长度 \(n\) 的序列 \(x\),可以进行如下操作:

  1. 花费 \(a\) 的代价将任意一个元素的值增加 \(1\)

  2. 花费 \(b\) 的代价将任意一个元素的值减少 \(1\)

对于 \(\forall 1 \le i \le n\),求最小的代价使得 \(x_1 = x_2 = \ldots = x_i\)

分析

可以用一种神奇的数据结构来维护当前点左右两边的点的数量,就比如对顶堆,然后就《氢松》完成了这道题。

时间复杂度:\(O(n \log_2 n)\)

考场寄因

挂分:\(\text{0pts}\)

原因:没挂

代码

点击查看代码
#include <bits/stdc++.h>

#define IOS ios::sync_with_stdio(0);\
	cin.tie(0), cout.tie(0)
#define int long long

using namespace std;

const int kMaxN = 1e5 + 5;

int n, a, b;
int x[kMaxN];
int sump, sumq, sum;
int rt, lt;
priority_queue<int> p;
priority_queue<int, vector<int>, greater<int> > q;

signed main() {
	IOS;
	cin >> n >> a >> b;
	for (int i = 1; i <= n; i++) {
		cin >> x[i];
		if (!p.size() || p.top() > x[i]) {
			p.push(x[i]);
			sump += x[i];
		} else {
			q.push(x[i]);
			sumq += x[i];
		}
		if (sum >= x[i]) {
			lt = b * i / (a + b) + 1;
		} else {
			rt = a * i / (a + b);
			lt = i - rt;
		}
		for (; p.size() < lt; p.push(q.top()), q.pop()) {
			sump += q.top();
			sumq -= q.top();
		}
		for (; p.size() > lt; q.push(p.top()), p.pop()) {
			sump -= p.top();
			sumq += p.top();
		}
		sum = p.top();
		cout << (sum * p.size() - sump) * a + (sumq - sum * q.size()) * b << '\n';
	}
	return 0;
}

\(\texttt{D}\)

题意

给定一棵树,定义一条长度为 \(d\) 的简单路径的权值为 \(2^d\),询问 \(q\) 次,每次询问经过 \(x, y\) 两点的所有简单路径的长度之和。

分析

咕咕咕。

考场寄因

咕咕咕。

代码

点击查看代码
咕咕咕。
posted @ 2023-10-08 15:36  Yun_Mengxi  阅读(23)  评论(0)    收藏  举报