Official

N - 400億マス計算 / 40B of calculations Editorial by physics0523


本問題より難しい以下の問題を解くことができれば、明らかに本問題も解けます。

(マス計算をする所までは本問題と同じ)
任意の整数 \(x\) に対して、値 \(x\) が書き込まれたマスが何個あるか求めよ。

突然ですが、
多項式 \(P=x^{A_1-1}+x^{A_2-1}+\dots+x^{A_N-1}\)
多項式 \(Q=x^{200000-A_1}+x^{200000-A_2}+\dots+x^{200000-A_N}\)
を考えてみましょう。
\(P\)\(i\) 項目と \(Q\)\(j\) 項目を掛けると \(x^{A_i-1+200000-A_j}\) となります。ここで、指数部 \(A_i-1+200000-A_j\) は上から \(i\) 番目、左から \(j\) 番目のマスに書き込まれる数に \(199999\) を加えたものに他なりません。
よって、多項式の積として \(P \times Q\) を求めた時、 \(x^k\) の項につく係数はマス目に \(k-199999\) が書かれる回数に一致します。
よって、 \(P \times Q\) を多項式の積として求め、係数が \(0\) でない項の総数を求めればそれが本問題の答えになります。
なお、2つの多項式の積は ACL に実装されている Convolution を使うことで求められます。
ここで、各項を \(\mod M\) (例えば \(M=998244353\)) で求めるといった畳み込みでは上手くいかないことに注意してください。なぜなら、係数が非零な \(M\) の倍数であったときに「係数は \(0\) である」との誤審を起こしてしまうからです。
ACL を用いる場合、 convolution_ll を利用しましょう。

#include<bits/stdc++.h>
#include<atcoder/all>

using namespace std;
using namespace atcoder;

int main(){
  int n;
  cin >> n;
  vector<int> a(n);
  for(auto &nx : a){cin >> nx;}
  vector<long long> p(200000,0),q(200000,0);
  for(auto &nx : a){
    p[nx-1]++;
    q[200000-nx]++;
  }
  vector<long long> r=convolution_ll(p,q);
  int res=0;
  for(auto &nx : r){
    if(nx!=0){res++;}
  }
  cout << res << '\n';
  return 0;
}

posted:
last update: