結果
| 問題 |
No.206 数の積集合を求めるクエリ
|
| コンテスト | |
| ユーザー |
koyumeishi
|
| 提出日時 | 2015-05-09 00:57:14 |
| 言語 | C++11(廃止可能性あり) (gcc 13.3.0) |
| 結果 |
AC
|
| 実行時間 | 256 ms / 7,000 ms |
| コード長 | 3,472 bytes |
| コンパイル時間 | 765 ms |
| コンパイル使用メモリ | 92,904 KB |
| 実行使用メモリ | 26,788 KB |
| 最終ジャッジ日時 | 2024-07-05 20:55:48 |
| 合計ジャッジ時間 | 4,497 ms |
|
ジャッジサーバーID (参考情報) |
judge5 / judge1 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 3 |
| other | AC * 28 |
ソースコード
#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;
}
koyumeishi