【LOJ2261】「CTSC2017」密钥

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_39972971/article/details/83619130

【题目链接】

【思路要点】

  • 使用一个简单的扫描线可以求出 XX 在每个位置处的特征值。
  • 时间复杂度 O(N)O(N)

【代码】

#include<bits/stdc++.h>
using namespace std;
const int MAXN = 2e7 + 5;
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("");
}
bool p[MAXN];
int seed, n, k, s;
int getrand() {
	seed = ((seed * 12321) ^ 9999) % 32768;
	return seed;
}
void generateData() {
	scanf("%d%d%d", &k, &seed, &s);
	int t = 0;
	n = k * 2 + 1;
	for (int i = 1; i <= n; i++) {
		p[i] = getrand() >> 7 & 1;
		t += p[i];
	}
	int i = 1;
	while(t > k) {
		while (p[i] == 0) i++;
		p[i] = 0; t--;
	}
	while(t < k) {
		while (p[i] == 1) i++;
		p[i] = 1; t++;
	}
}
int val[MAXN];
int solve(int x, bool type) {
	memset(val, 0, sizeof(val));
	int cipher = k + 2, now = cipher, pos = cipher;
	for (int i = 1; i <= n; i++)
		if (p[i] ^ type) val[++pos]++;
		else pos--;
	int sum = 0;
	for (int i = now + 1; i <= n + 2; i++)
		sum += val[i];
	for (int i = 1; i <= n; i++) {
		if (p[i] ^ type) sum -= val[++now], val[now]--;
		else sum += val[now--];
		if (!p[i] && sum == x) return i;
		if (p[i] ^ type) {
			val[++pos]++;
			if (pos > now) sum++;
		} else pos--;
	}
	assert(false);
	return -1;
}
int main() {
	generateData();
	printf("%d\n%d\n%d\n", solve(0, false), solve(s, false), solve(s, true));
	return 0;
}
阅读更多

没有更多推荐了,返回首页