結果

問題 No.206 数の積集合を求めるクエリ
ユーザー koyumeishikoyumeishi
提出日時 2015-05-09 00:57:14
言語 C++11
(gcc 11.4.0)
結果
AC  
実行時間 323 ms / 7,000 ms
コード長 3,472 bytes
コンパイル時間 1,126 ms
コンパイル使用メモリ 90,720 KB
実行使用メモリ 27,064 KB
最終ジャッジ日時 2023-09-19 09:11:02
合計ジャッジ時間 6,219 ms
ジャッジサーバーID
(参考情報)
judge15 / judge13
このコードへのチャレンジ(β)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 1 ms
4,380 KB
testcase_01 AC 1 ms
4,384 KB
testcase_02 AC 2 ms
4,384 KB
testcase_03 AC 2 ms
4,384 KB
testcase_04 AC 2 ms
4,384 KB
testcase_05 AC 2 ms
4,384 KB
testcase_06 AC 5 ms
4,380 KB
testcase_07 AC 5 ms
4,380 KB
testcase_08 AC 5 ms
4,384 KB
testcase_09 AC 5 ms
4,380 KB
testcase_10 AC 2 ms
4,380 KB
testcase_11 AC 2 ms
4,380 KB
testcase_12 AC 10 ms
4,384 KB
testcase_13 AC 9 ms
4,380 KB
testcase_14 AC 9 ms
4,384 KB
testcase_15 AC 9 ms
4,380 KB
testcase_16 AC 9 ms
4,380 KB
testcase_17 AC 194 ms
27,064 KB
testcase_18 AC 172 ms
26,532 KB
testcase_19 AC 188 ms
26,676 KB
testcase_20 AC 164 ms
26,492 KB
testcase_21 AC 177 ms
26,616 KB
testcase_22 AC 177 ms
26,636 KB
testcase_23 AC 193 ms
26,820 KB
testcase_24 AC 323 ms
26,920 KB
testcase_25 AC 321 ms
26,868 KB
testcase_26 AC 294 ms
26,380 KB
testcase_27 AC 260 ms
26,568 KB
testcase_28 AC 309 ms
26,512 KB
testcase_29 AC 301 ms
26,504 KB
testcase_30 AC 299 ms
26,320 KB
権限があれば一括ダウンロードができます

ソースコード

diff #

#include <iostream>
#include <vector>
#include <cstdio>
#include <sstream>
#include <map>
#include <string>
#include <algorithm>
#include <queue>
#include <cmath>
#include <set>
#include <complex>
using namespace std;

template<typename T = double>
class Fast_Fourier_Transform{
	// return the vector of F[t] or f[x] where
	// F[t] = sum of { f[x] * exp(-j * theta * t * x) } in x = 0 .. N-1 (FFT)
	// f(x) = 1/N * sum of { F[t] * exp(j * theta * t * x) } in t = 0 .. N-1 (inverse FFT)
	// where theta = 2*PI / N
	// N == 2^k
	static vector< complex<T> > do_fft(vector< complex<T> > A, bool inverse){
		const T PI = atan2(1, 0) * 2.0;
		const complex<T> j = complex<T>(0,1); // 0 + j*1.0 (j is the imaginary unit)

		int N = A.size();
		int k = 0;	// N = 2^k
		while(N>>k > 0) k++;
		
		for(int bit=0; bit<N; bit++){
			int rbit = 0;
			for(int i=0, tmp_bit = bit; i<k-1; i++, rbit <<= 1, tmp_bit >>=  1){
				rbit |= tmp_bit & 1;
			}
			rbit >>= 1;
			if(bit < rbit){
				swap(A[bit], A[rbit]);
			}
		}

		int dist = 1;
		T theta = -PI;
		if(inverse) theta = -theta;

		for(int level = 1; level<k; level++){
			complex<T> W_n = exp(j * theta);
			complex<T> W(1,0);
			for(int x=0; x < (1<<level-1); x++){
				for(int y=x; y+dist < N; y += (dist<<1)){
					complex<T> tmp = A[ y+dist ] * W;
					A[ y+dist ] = A[ y ] - tmp;
					A[ y ] += tmp;
				}
				W *= W_n;
			}
			dist <<= 1;
			theta *= 0.5;
		}

		if(inverse){
			T k = 1.0/N;
			for(int i=0; i<N; i++){
				A[i] *= k;
			}
		}
		return A;
	}


	template<typename U=T>
	static void vec_resize(vector<U> &A, const U val){
		int n = A.size();
		int k = 1;
		while(n > k) k<<=1;
		A.resize(k, val);
	}

public:
	Fast_Fourier_Transform(){};

	static vector< complex<T> > FFT(vector< complex<T> > A){
		vec_resize<complex<T>>(A, complex<T>(0,0));
		return do_fft(A, false);
	}

	static vector< complex<T> > IFFT(vector< complex<T> > A){
		//vec_resize<complex<T>>(A, complex<T>(0,0));
		return do_fft(A, true);
	}

	static vector< complex<T> > FFT(vector<T> A){
		vec_resize<T>(A, 0);
		vector<complex<T>> B(A.size());
		for(int i=0; i<B.size(); i++){
			B[i] = complex<T>(A[i], 0);
		}

		return do_fft(B, false);
	}

	static vector< complex<T> > FFT(vector<int> A){
		vec_resize<int>(A, T(0));
		vector<complex<T>> B(A.size());
		for(int i=0; i<B.size(); i++){
			B[i] = complex<T>(A[i], 0);
		}
		return do_fft(B, false);
	}

	static vector<int> round(vector<complex<T>> &&A){
		vector<int> ret(A.size());
		for(int i=0; i<A.size(); i++){
			ret[i] = A[i].real() + (A[i].real()<0?-0.5:0.5);
		}
		return ret;
	}

	// vector<double> C | C[i] = ΣA[i]B[j]
	static vector<complex<T>> combolution(vector<T> &A, vector<T> &B){
		reverse(B.begin(), B.end());

		int n = max(A.size(), B.size());
		A.resize(n, 0);
		B.resize(n, 0);

		auto A_FFT = FFT(A);
		auto B_FFT = FFT(B);
		for(int i=0; i<n; i++){
			A_FFT[i] *= B_FFT[i];
		}
		return IFFT(A_FFT);
	}
};

int main(){
	int L,M,N;
	cin >> L >> M >> N;
	vector<int> A(L), B(M);
	for(int i=0; i<L; i++){
		cin >> A[i];
	}
	for(int i=0; i<M; i++){
		cin >> B[i];
	}
	int Q;
	cin >> Q;

	int sz = 1;
	while(N >= sz) sz <<= 1;

	vector<double> A_(sz*2, 0);
	for(int i=0; i<A.size(); i++){
		A_[A[i]] = 10;
	}

	vector<double> B_(sz, 0);
	for(int i=0; i<B.size(); i++){
		B_[B[i]] = 10;
	}

	auto C = Fast_Fourier_Transform<double>::round(Fast_Fourier_Transform<double>::combolution(A_, B_));

	for(int i=0; i<Q; i++){
		cout << C[sz-1+i]/100 << endl;
	}

	return 0;
}
0