CSP模拟-8

今天T1终于看懂辣。。。。但今天名次最低QAQ。T1没算空间复杂度,直接炸QAQ

T1 Coprime 2

今天T1确实简单,将输入的数的质数公因数用埃氏筛筛出来,用一个数组存下来。每次将质因数的倍数用 \(flag\) 存下 \(true\) ,表示这个数存在因数与输入的数重复的情况,让后就没有辣。

正确性的话:一个合数因数一定会被分解成一个或多个质因数,所以每次找质因数就行辣。(我相信你们都明白吧QAQ)

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <vector> 

using namespace std;

int n, a[5211314], m;
int gcd_sum, ans[2000010], sum, is_gcd[2000010], rec_gcd[2000010];
bool barrel[2000010], is_prime[2000010], flag[2000010];

void Prime() {
	//正经的埃氏筛
	memset(is_prime, true, sizeof(is_prime));
	for (int i = 2; i <= m; ++ i) {
		if (is_prime[i] == false) continue;
		for (int j = i; j <= m; j = j + i) {
			is_prime[j] = false;
			//找输入的数的质因数
			if (barrel[j] == true && rec_gcd[i] == false) {
				//如果i的倍数是输入的数并且质因数i没有被存过
				is_gcd[++ gcd_sum] = i;
				rec_gcd[i] = true;
				//这里记录的原因是保证复杂度
			}
		}
	}
	return;
}

int main() {
	scanf("%d%d", &n, &m);
	for (int i = 1; i <= n; ++ i) {
		scanf("%d", &a[i]);
		barrel[a[i]] = true;
		//将输入的数用桶先存下来
	}
	Prime();
	for (int i = 1; i <= gcd_sum; ++ i) {
		for (int j = is_gcd[i]; j <= m; j += is_gcd[i]) {
			//将每个质数因数的倍数标记
			flag[j] = true;
		}
	}
	for (int i = 1; i <= m; ++ i) {
		if (flag[i] == false) {
			//不存在输入的数的质因数
			ans[++ sum] = i;
		}
	}
	//输出
	printf("%d\n", sum);
	for (int i = 1; i <= sum; ++ i) {
		printf("%d\n", ans[i]);
	}
	return 0;
}

T2 Dist Max 2

又是逆天二分QAQ,永远写不对的边界条件,我真服了。

看见找最小值的最大值,一眼丁真鉴定为二分答案

设我们现在已经枚举到 \(mid\),所以我们这时必定会存在 \(i, j\) 满足 \(\left| x_i - x_j \right| \geq mis\) 并且满足 \(\left| y_i - y_j \right| \geq mid\)

此时我们直接遇事不决先排序,将点以 \(x\) 为关键字进行升序排序,然后维护双指针就行了。

我们的双指针 \(l,r\) 表示左区间 \(1 \sim l\)\(l\) 为结尾,右区间 \(r \sim n\)\(r\) 为右端点。这时我们要保证区间 \(1 \sim l\) 的每一个点的横坐标与区间 \(r \sim n\) 的每一个点的横坐标的差大于我们二分到的 \(mid\)。将这两个符合差为 \(mid\) 要求的区间内点的纵坐标 \(Y\) 的最大值与最小值分别与另一区间内纵坐标 \(Y\) 的最小值最大值作差,判断是否大于等于 \(mid\)。若大于,则符合题目要求,返回真。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>

using namespace std;

int n;

struct Picture {
	int x, y;
	bool operator < (const Picture & b) const {
		if (x != b.x) return x < b.x;
		return y < b.y;
	}//sort的时候用 
}a[1000100];

bool check(int differ) {
	int MaxY = -1e9, MinY = 1e9;
	//在l之前Y轴的最值 
	for (int r = 1, l = 0; r <= n; ++ r) { 
		//这里面的l表示左半部分的右端点,r表示右半部分的左端点
		//l就是左指针,r就是右指针 
		while (l < r && a[r].x - a[l + 1].x >= differ) {
			//若存在更小的X轴之差符合差最小值得differ的条件,就更新l的值 
			MaxY = max(MaxY, a[l + 1].y);
			MinY = min(MinY, a[l + 1].y);
			//将左指针新包含的范围内的MaxY和MinY更新 
			l ++;
		}
		if (MaxY - a[r].y >= differ) return true;
		if (a[r].y - MinY >= differ) return true;
		//判断左边的Y的最值与右侧的Y的最值的差是不是大于differ 
		//在循环里我们相当于将右指针后面的数全部枚举了一遍最大值,最小值 
		//左指针除了l=r=1的时候处理右指针,其他时候都是左指针跟着右指针移动
		//所以在右指针更新的时候,左指针左边的MaxY与MinY也都被更新了,正确性可以保证 
	}
	return false;
}

int main() {
	scanf("%d", &n);
	for (int i = 1; i <= n; ++ i) {
		scanf("%d%d", &a[i].x, &a[i].y);
	}
	sort(a + 1, a + 1 + n);
	int l = 0, r = 1e9, ans = 0;
	while (l <= r) {
		//二分找最值 
		int mid = (l + r) >> 1;
		if (check(mid)) {
			l = mid + 1;
			ans = mid;
		}
		else r = mid - 1;
	}
	printf("%d\n", ans);
	return 0;
}

PS:顺带附上找最最大的最小值

while (l <= r) {
	int mid = (l + r) >> 1;
	if (check(mid)) {
		r = mid - 1;
		ans = mid;
	}
	else l = mid + 1;
}

T3 [ABC221H] Count Multiset

这边建议[这篇题解](「解题报告」[ABC221H] Count Multiset - K8He - 洛谷博客 (luogu.com.cn))。写的很好,复杂度优。

#include <iostream>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <cstdio>

#define mod 998244353

using namespace std;
typedef long long ll;

int n, m, f[5210][5210], g[5210][5210], sum[5210][5210];

int main() {
	scanf("%d%d", &n, &m);
	for (int i = 1; i <= n; ++ i) {
		if (i <= m) 
			f[i][0] = 1;
		for (int j = 1; j <= n; ++ j) {
			if (j >= i) 
				f[i][j] = g[i][j] = f[i][j - i];
			sum[i][j] = (sum[i - 1][j] + g[i][j]) % mod;
			f[i][j] = ((f[i][j] + sum[i - 1][j]) % mod - sum[max(0, i - m - 1)][j] + mod) % mod;
		}
	}
	for (int i = 1; i <= n; ++ i) {
		cout << g[i][n] << endl;
	}
	return 0;
}

T4 Julia the snail

数据加强版,吉司机线段树不会,咕。

总结

本次考试分数最高,但名词最低QAQ。T1直接炸,没考虑空间复杂度,下一次不能再犯辣。T2没看见是整数,不敢开 \(long long\),开了 \(longdouble\) 输出浮点,又炸。![[23FDBE81.jpg]]

posted @ 2023-07-28 20:38  觉清风  阅读(42)  评论(0编辑  收藏  举报