CSP-24-3 登机牌条码

大模拟 + 多项式除法

原题链接: https://www.acwing.com/problem/content/4285/

这道大模拟和以往的不太一样,模拟部分很简单,难点在于多项式除法部分。
对于下面的描述,如何看出要求的是多项式除法呢?

因为 xk、g(x)、d(x)均已知,要求q(x)和r(x),这就相当于被除数xk * d(x)已知,在同余条件下,除数g(x)也已知,要去求商q(x)和余数r(x)。

那么如何进行多项式的除法呢?


以这一题为例,其实多项式除法就类似于正常数的除法,不同点在于:

1.每次消除被除数的最高位,确保处理后的除数的最高项的次数和系数与被除数的最高项的次数和系数分别相等。其实这就确定了每一步的商。

2.在除法运算的过程中,在每一次除法结束后停止,都能保证正确。比如,除法运行两次后,得到部分商 12x^2 - 3x,部分余数 5x + 1,将部分商和部分余数带回原始中,能保证原式的等式仍成立。

题目要求:r是不高于k-1次的多项式,所以我们需要余数到 k - 1 次时就停下来。

PS: vector code; code.insert(code.begin(), (int)code.size() + 1);

vector也有insertAPI,通常,第一个参数是插入位置(迭代器表示),第二个参数是插入的内容。

#include <bits/stdc++.h>
using namespace std;

typedef long long LL;

const LL MOD = 929;

int w, s;
string str;
vector<LL> code;
vector<LL> v;
// 0 小写 1 大写 2 数字
int st = 1;

bool is_Bigchar(char c) {
	if (c <= 'Z' && c >= 'A')
		return true;
	return false;
}

bool is_Smallchar(char c) {
	if (c <= 'z' && c >= 'a')
		return true;
	return false;
}

bool is_Number(char c) {
	if (c <= '9' && c >= '0')
		return true;
	return false;
}

int main() {
	cin >> w >> s;
	cin >> str;

	int len_s = (s == -1 ? 0 : (int)pow(2, s + 1));

	for (int i = 0; i < str.size(); i++) {
		if (st == 0) {
			if (is_Bigchar(str[i])) {
				v.push_back(28);
				v.push_back(28);
				st = 1;
				v.push_back((int)(str[i] - 'A'));
			} else if (is_Smallchar(str[i])) {
				v.push_back((int)(str[i] - 'a'));
			} else {
				v.push_back(28);
				v.push_back((int)(str[i] - '0'));
				st = 2;
			}
		} else if (st == 1) {
			if (is_Bigchar(str[i])) {
				v.push_back((int)(str[i] - 'A'));
			} else if (is_Smallchar(str[i])) {
				v.push_back(27);
				v.push_back((int)(str[i] - 'a'));
				st = 0;
			} else {
				v.push_back(28);
				v.push_back((int)(str[i] - '0'));
				st = 2;
			}
		} else if (st == 2) {
			if (is_Bigchar(str[i])) {
				v.push_back(28);
				v.push_back((int)(str[i] - 'A'));
				st = 1;
			} else if (is_Smallchar(str[i])) {
				v.push_back(27);
				v.push_back((int)(str[i] - 'a'));
				st = 0;
			} else {
				v.push_back((int)(str[i] - '0'));
			}
		}
	}

	if ((int)(v.size()) % 2 != 0) {
		v.push_back(29);
	}

	for (int i = 0; i < v.size(); i += 2) {
		code.push_back(v[i] * 30 + v[i + 1]);
	}

	int tmp_l = ((int)code.size() + 1 + len_s) % w;
	if (tmp_l != 0) {
		for (int i = 0; i < w - tmp_l; i++) {
			code.push_back(900);
		}
	}

	code.insert(code.begin(), (int)code.size() + 1);

	int n = code.size();
	int k = len_s;

	vector<LL> d(n + len_s, 0);
	vector<LL> g(n + len_s, 0);

	for (int i = 0; i <= n - 1; i++) {
		d[n + k - 1 - i] = code[i] % MOD;
	}

	g[0] = 1;
	int g_top = 0; //gx函数的最高次项
	int exp = 1;
	vector<int> mul(2);
	mul[1] = 1;
	for (int i = 0; i < k; ++ i) {
		vector<LL> tmp(n + k, 0);
		exp = (exp * 3 ) % MOD;
		mul[0] = -exp;
		for (int j = 0; j <= g_top ; ++j)
			for (int l = 0; l <= 1; ++ l) {
				tmp[j + l] = (tmp[j + l] % MOD + (g[j] % MOD) * (mul[l] % MOD) ) % MOD;
			}
		g = tmp;
		g_top += 1;
	}

	/*
	多项式除法
	*/
	int d_top = n + len_s - 1;
	while (d_top >= len_s) {
		int div = d[d_top] / g[g_top];
		for (int i = 0; i <= g_top; i++) {
			d[d_top - i] = ((d[d_top - i] % MOD) - (div % MOD) * (g[g_top - i] % MOD)) % MOD;
		}
		d_top--;
	}

	for (int i = k - 1; i >= 0; i--) {
		code.push_back(((-d[i] % MOD) + MOD) % MOD);
	}


	for (int i = 0; i < code.size(); i++) {
		printf("%d\n", code[i]);
	}

	return 0;
}

参考博客:

https://blog.csdn.net/shn111/article/details/123433540

https://www.acwing.com/solution/content/80735/

posted @ 2022-05-27 12:05  superPG  阅读(115)  评论(0编辑  收藏  举报