QOJ.ac

QOJ

ID题目提交者结果用时内存语言文件大小提交时间测评时间
#135643#6399. Classic: Classical ProblemUrgantTeam#WA 1ms3868kbC++237.4kb2023-08-05 20:02:242023-08-05 20:02:27

Judging History

你现在查看的是最新测评结果

  • [2023-08-10 23:21:45]
  • System Update: QOJ starts to keep a history of the judgings of all the submissions.
  • [2023-08-05 20:02:27]
  • 评测
  • 测评结果:WA
  • 用时:1ms
  • 内存:3868kb
  • [2023-08-05 20:02:24]
  • 提交

answer

#pragma GCC optimize("Ofast,unroll-loops")
#define _CRT_SECURE_NO_WARNINGS
#define _USE_MATH_DEFINES
#define X first
#define Y second
#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
using namespace std;
using vi = vector<int>;
using ll = int64_t;
using vb = vector<bool>;
int prod(int a, int b, int p) {
	return ll(a) * b % p;
}
bool cpr(const int g, const int p) {
	int u = 1;
	for (int i = 1; i <= p - 2; ++i) {
		u = prod(u, g, p);
		if (u == 1) return false;
	}
	return true;
}
int pr(const int p) {
	for (int g = 2;; ++g)
		if (cpr(g, p))
			return g;
}
pair<vi, vi> logs(int p) {
	int g = pr(p);
	vi ans(p);
	vi powers(p - 1, 1);
	for (int i = 0, u = 1; i < p - 1; ++i) {
		ans[u] = i;
		powers[i] = u;
		u = prod(u, g, p);
	}
	return { ans, powers };
}
namespace FFT {
	using db = float;
	template<class T>
	struct Compl {
		T real, image;
		Compl(T r = 0, T i = 0) : real(r), image(i) {}
		Compl operator+(const Compl& c) const {
			return { real + c.real, image + c.image };
		}
		Compl operator-(const Compl& c) const {
			return { real - c.real, image - c.image };
		}
		Compl operator*(const Compl& c) const {
			return { real * c.real - image * c.image, image * c.real + c.image * real };
		}
		Compl operator/(const T& c) const {
			return { real / c, image / c };
		}
		Compl& operator=(const Compl& a) {
			real = a.real;
			image = a.image;
			return *this;
		}
		Compl& operator=(const db& a) {
			real = a;
			image = 0;
			return *this;
		}
	};
	using Complex = Compl<db>;
	struct FFT {
		const int n = 20;
		const int size = (1 << n);
		vector<Complex> root;
		vi revers;
		vector<Complex> fftA, fftB;
		FFT(int _n) : size(1 << _n), n(_n) {
			revers.resize(size), root.resize(size);
			fftA.resize(size); fftB.resize(size);
			for (int i = 0; i < size / 2; ++i) {
				root[i] = Complex(cos(2 * M_PI * i / size), sin(2 * M_PI * i / size));
				root[i + size / 2] = Complex(-root[i].real, -root[i].image);
			}
		}
		void fft(vector<Complex>& poly, int newN) {
			revers[0] = 0;
			for (int i = 1; i < 1 << newN; ++i) {
				if (i % 2 == 0) revers[i] = revers[i / 2] / 2;
				else revers[i] = revers[i / 2] / 2 + (1 << (newN - 1));
				if (revers[i] < i) swap(poly[revers[i]], poly[i]);
			}
			for (int level = 1; level <= newN; ++level)
				for(int block = 0; block < (1 << (newN - level)); ++block)
					for (int step = 0; step < (1 << (level - 1)); ++step) {
						int num1 = (block << level) + step;
						int num2 = num1 + (1 << level - 1);
						Complex valA = poly[num1];
						Complex valB = root[step << (n - level)] * poly[num2];
						poly[num1] = valA + valB;
						poly[num2] = valA - valB;
					}
		}
		void rev_fft(vector<Complex>& poly, int step) {
			fft(poly, step);
			reverse(poly.begin() + 1, poly.begin() + (1 << step));
			for (int i = 0; i < (1 << step); ++i) poly[i] = poly[i] / (1 << step);
		}
		vector<db> multiply(const vector<db>& A, const vector<db>& B, int step) {
			fill(fftA.begin(), fftA.begin() + (1 << step), 0.);
			fill(fftB.begin(), fftB.begin() + (1 << step), 0.);
			copy(A.begin(), A.end(), fftA.begin());
			copy(B.begin(), B.end(), fftB.begin());
			fft(fftA, step); fft(fftB, step);
			for (int i = 0; i < (1 << step); ++i)
				fftA[i] = fftA[i] * fftB[i];
			rev_fft(fftA, step);
			vector<db> result(1 << step);
			for (int i = 0; i < (1 << step); ++i)
				result[i] = fftA[i].real;
			return result;
		}
	};

}
using vf = vector<float>;
int clo(int n) {
	for (int i = 31; i >= 0; --i)
		if (n & (1 << i)) return i;
}
pair<int, vi> check_occur_naive(const vb& pattern, const vb& text, const int sum) {
	vi pi;
	int P = pattern.size(), T = text.size();
	for (int i = 0; i < P; ++i)
		if (pattern[i]) pi.push_back(i);
	int lans = 0;
	vi ans;
	for (int i = 0; i < T - P + 1; ++i) {
		int cans = 0;
		for (int j : pi)
			if (text[i + j])
				++cans;
		lans = max(lans, cans);
		if (cans >= sum)
			ans.push_back(i);
	}
	return { lans, ans };
}
pair<int, vi> check_occur(const vb& pattern, const vb& text) {
	int sum = 0;
	for (bool i : pattern)
		sum += i;
	if (sum <= 200) return check_occur_naive(pattern, text, sum);
	static FFT::FFT fft(20);
	int P = pattern.size(), T = text.size();
	vf rpattern(P);
	for (int i = 0; i < P; ++i)
		rpattern[i] = pattern[P - 1 - i];
	vf txt(text.begin(), text.end());
	int expected_degree = txt.size() + rpattern.size() - 1;
	vf prd = fft.multiply(rpattern, txt, 1 + clo(expected_degree - 1));
	vi ans;
	int lans = 0;
	for (int i = P - 1; i < T; ++i) {
		int prdint = prd[i] + .5;
		if (prdint >= sum)
			ans.push_back(i - P + 1);
		lans = max(lans, prdint);
	}
	return { lans, ans };
}
int dif(int a, int b, int m) {
	if ((a -= b) < 0) a += m;
	return a;
}
int summ(int a, int b, int m) {
	if ((a += b) >= m) a -= m;
	return a;
}
pair<int, vi> find_ans(const vi& a, const int p) {
	auto it = find(a.begin(), a.end(), 0);
	if (it == a.end())
		return { 1, {0} };
	if (a.size() == 1) {
		vi a(p);
		for (int i = 1; i < p; ++i)
			a[i] = i;
		return { 1, a };
	}
	auto [l, pw] = logs(p);
	vb lgs(p - 1);
	for (int i : a)
		if (i)
			lgs[l[i]] = true;
	vb lgslgs = lgs;
	for (bool b : lgs) lgslgs.push_back(b);
	lgslgs.pop_back();
	int left = -1, right = a.size();
	vi best_incls;
	while (right - left >= 2) {
		int med = (left + right) / 2;
		cerr << "[" << left << "; " << right << "] -> med;\n";
		vb pattern(p - 1);
		for (int i = 1; i <= med; ++i)
			pattern[l[i]] = true;
		auto [lans, incls] = check_occur(pattern, lgslgs);
		if (incls.empty())
			right = lans + 1;
		else {
			int actual_ans = med;
			for (int i : best_incls) {
				if (actual_ans > med)
					break;
				for (; actual_ans < p - 1; ++actual_ans)
					if (!lgslgs[i + l[actual_ans + 1]])
						break;
			}
			left = actual_ans;
			if (med == actual_ans)
				best_incls.swap(incls);
			else
				best_incls.clear();
		}
	}
	if (best_incls.empty()) {
		vb pattern(p - 1);
		for (int i = 1; i <= left; ++i)
			pattern[l[i]] = true;
		best_incls = check_occur(pattern, lgslgs).Y;
	}
	for (int& i : best_incls)
		i = pw[dif(0, i, p - 1)];
	sort(best_incls.begin(), best_incls.end());
	return {right, best_incls};
}
void solve_test() {
	int n, p;
	cin >> n >> p;
	vi a(n);
	for (int& i : a) cin >> i;
	pair<int, vi> ans = find_ans(a, p);
	cout << ans.Y.size() << ' ' << ans.X << '\n';
	for (int i = 0; i < ans.Y.size(); ++i)
		cout << ans.Y[i] << " \n"[i + 1 == ans.Y.size()];
}
void solve_tests() {
	cerr << "Began!\n";
	int t;
	cin >> t;
	for (int i = 0; i < t; ++i)
		solve_test();
	cerr << "Finished!\n";
}
#include <random>
#include <fstream>
#include <chrono>
using namespace std;
void generate_test() {
	int p = 199999;
	int m = 140000;
	ofstream fout("input.txt");
	fout << 1 << '\n' << m << ' ' << p << '\n';
	fout << 0;
	vi v(p - 1);
	for (int i = 1; i < p; ++i) v[i - 1] = i;
	mt19937 rng;
	shuffle(v.begin(), v.end(), rng);
	for (int i = 0; i < m - 1; ++i)
		fout << ' ' << v[i];
	fout << '\n';
}
int main() {
#ifdef HOME
	//generate_test();
	freopen("input.txt", "r", stdin);
	freopen("output.txt", "w", stdout);
#endif
	ios_base::sync_with_stdio(0); cin.tie(0);
	auto start_time = chrono::high_resolution_clock::now();
	solve_tests();
	auto end_time = chrono::high_resolution_clock::now();
	cerr << "Spent: " << (end_time - start_time) / 1.ms << " ms\n";
}

详细

Test #1:

score: 0
Wrong Answer
time: 1ms
memory: 3868kb

input:

3
2 3
0 2
3 5
2 3 4
3 5
0 2 3

output:

0 2
1 1
0
2 2
2 3

result:

wrong answer 1st lines differ - expected: '1 2', found: '0 2'