【LOJ573】「LibreOJ NOI Round #2」单枪匹马

这篇博客主要介绍了LOJ573问题的解题思路,作者提供了官方题解链接,并指出算法的时间复杂度为O(N+M)。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

【题目链接】

【思路要点】

  • 官方题解 。(反正也是我写的)
  • 时间复杂度 O ( N + M ) O(N+M) O(N+M)

【代码】

#include<bits/stdc++.h>
using namespace std;
const int MAXN = 1e6 + 5;
const int P = 998244353;
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
template <typename T> void chkmax(T &x, T y) {x = max(x, y); }
template <typename T> void chkmin(T &x, T y) {x = min(x, y); } 
template <typename T> void read(T &x) {
	x = 0; int f = 1;
	char c = getchar();
	for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
	for (; isdigit(c); c = getchar()) x = x * 10 + c - '0';
	x *= f;
}
template <typename T> void write(T x) {
	if (x < 0) x = -x, putchar('-');
	if (x > 9) write(x / 10);
	putchar(x % 10 + '0');
}
template <typename T> void writeln(T x) {
	write(x);
	puts("");
}
struct Mat {int a[2][2]; };
Mat operator * (Mat a, Mat b) {
	Mat ans;
	ans.a[0][0] = (1ll * a.a[0][0] * b.a[0][0] + 1ll * a.a[0][1] * b.a[1][0]) % P;
	ans.a[0][1] = (1ll * a.a[0][0] * b.a[0][1] + 1ll * a.a[0][1] * b.a[1][1]) % P;
	ans.a[1][0] = (1ll * a.a[1][0] * b.a[0][0] + 1ll * a.a[1][1] * b.a[1][0]) % P;
	ans.a[1][1] = (1ll * a.a[1][0] * b.a[0][1] + 1ll * a.a[1][1] * b.a[1][1]) % P;
	return ans;
}
int n, m, type, a[MAXN];
Mat mat[MAXN], inv[MAXN];
Mat getmat(int x) {
	Mat ans;
	ans.a[0][0] = 0, ans.a[0][1] = 1;
	ans.a[1][0] = 1, ans.a[1][1] = x;
	return ans;
}
Mat getinv(int x) {
	Mat ans;
	ans.a[0][0] = P - x, ans.a[0][1] = 1;
	ans.a[1][0] = 1, ans.a[1][1] = 0;
	return ans;
}
int main() {
	read(n), read(m), read(type);
	mat[0].a[0][0] = mat[0].a[1][1] = 1;
	inv[0].a[0][0] = inv[0].a[1][1] = 1;
	for (int i = 1; i <= n; i++) {
		scanf("%d", &a[i]);
		assert(a[i] >= 1 && a[i] <= 998244352);
		mat[i] = mat[i - 1] * getmat(a[i]);
		inv[i] = getinv(a[i]) * inv[i - 1];
	}
	int lastx = 0, lasty = 0;
	for (int i = 1; i <= m; i++) {
		int opt, l, r, x;
		scanf("%d", &opt);
		if (opt == 1) {
			scanf("%d", &x);
			if (type == 1) x ^= lastx ^ lasty; a[++n] = x;
			assert(x >= 1 && x <= 998244352);
			mat[n] = mat[n - 1] * getmat(a[n]);
			inv[n] = getinv(a[n]) * inv[n - 1];
		}
		if (opt == 2) {
			scanf("%d %d", &l, &r);
			if (type == 1) l ^= lastx ^ lasty;
			if (type == 1) r ^= lastx ^ lasty;
			assert(1 <= l && l <= r && r <= n);
			Mat res = inv[l - 1] * mat[r];
			printf("%d %d\n", lastx = res.a[1][1], lasty = res.a[0][1]);
		}
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值