No.206 数の積集合を求めるクエリ
No.206 数の積集合を求めるクエリ - yukicoder
- A[i],B[i] の上限が高々 10^5 であることに着目して解く。
- 以下は他の人のコードを参考にして解いた。bitset 使うとこんなに簡単に書けるとは..。すげー。
class QueryOfNumberProductSet { public: void solve(void) { int L,M,N; cin>>L>>M>>N; // A[i],B[i] の上限が高々 10^5 であること // A,B にて同じ数字が存在しないこと // から A,B を bitset で扱うと A & B の計算、 B の一律加算が簡単に表現できる bitset<100001> A; bitset<100001> B; REP(i,L) { int x; cin>>x; A.set(x); } REP(i,M) { int x; cin>>x; B.set(x); } int Q; cin>>Q; // O(Q*N/64) REP(v,Q) { // 加算によってビットが左にずれる cout<<(A & (B<<v)).count()<<endl; } } };
class QueryOfNumberProductSet { public: void solve(void) { int L,M,N; cin>>L>>M>>N; // // f(x) = ∑ x^A[i] // g(x) = ∑ x^(N-B[i]) (次数がN-B[i]なのは畳み込み後の次数に A[i]-B[i] を入れたいから) // // とするとき // // (f*g)(x) = ∑∑ a[i]b[j] x^(A[i]-B[j]+N) // = ∑ c[i] x^i // // c[N+v] = #{(i,j) | (A[i]-B[j]+N == N+v) } となる // // よって FFT が使える // vector<double> a(N+1,0); vector<double> b(N+1,0); vector<double> c(2*(N+1),0); REP(i,L) { int x; cin>>x; // 次数に対応する係数だけ 1 にする a[x] = 1; } REP(i,M) { int x; cin>>x; b[N-x] = 1; } convolve(a,b,c); int Q; cin>>Q; REP(v,Q) { // round してから cast しないと期待どおりの値にならない cout<<(int)round(c[N+v])<<endl; } } };