Problem p02590 (C++) — buggy submission, verdict: Time Limit Exceeded

#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>

#define LL long long
#define Maxn 800005

using namespace std;

const LL P = 200003;
const double PI = acos(-1.0);

inline LL read() {
  LL x = 0, f = 1;
  char c = getchar();
  while (c < '0' || c > '9') {
    if (c == '-')
      f = -1;
    c = getchar();
  }
  while ('0' <= c && c <= '9') {
    x = x * 10 + c - '0';
    c = getchar();
  }
  return x * f;
}

LL n, m = 1, val[Maxn], mapp[Maxn], trans[Maxn], g[Maxn];

struct Point {
  double x, y;
} f[Maxn];

Point Plus(Point a, Point b) {
  Point c;
  c.x = a.x + b.x;
  c.y = a.y + b.y;
  return c;
}

Point Minus(Point a, Point b) {
  Point c;
  c.x = a.x - b.x;
  c.y = a.y - b.y;
  return c;
}

Point Mul(Point a, Point b) {
  Point c;
  c.x = a.x * b.x - a.y * b.y;
  c.y = a.x * b.y + b.x * a.y;
  return c;
}

void DFT(Point *F, bool op) {
  for (int i = 0; i < m; ++i)
    trans[i] = (trans[i >> 1] >> 1) | ((i & 1) ? m >> 1 : 0);
  for (int i = 0; i < m; ++i)
    if (i < trans[i])
      swap(F[i], F[trans[i]]);
  for (int len = 2; len <= m; len <<= 1) {
    Point base = {cos(2 * PI / len), sin(2 * PI / len)};
    if (op)
      base.y *= -1.0;
    for (int i = 0; i < m; i += len) {
      Point now = {1.0, 0.0};
      for (int k = i; k < i + (len >> 1); ++k) {
        Point temp = Mul(now, F[k + (len >> 1)]);
        F[k + (len >> 1)] = Minus(F[k], temp);
        F[k] = Plus(F[k], temp);
        now = Mul(now, base);
      }
    }
  }
}

int main() {
  n = read();
  for (int i = 1; i <= n; ++i)
    val[i] = read();
  LL mul = 1;
  for (int i = 0; i <= P - 2; ++i) {
    mapp[mul] = i;
    mul = mul * 2 % P;
  }
  for (int i = 1; i <= n; ++i)
    if (val[i])
      ++f[mapp[val[i]]].x;
  while (m < 2 * P - 3)
    m <<= 1;
  // cout << m << endl;
  DFT(f, 0);
  for (int i = 0; i < m; ++i)
    f[i] = Mul(f[i], f[i]);
  DFT(f, 1);
  for (int i = 0; i < m; ++i)
    g[i] = f[i].x * 1.0 / m + 0.5;
  LL ans = 0;
  mul = 1;
  for (int i = 1; i <= n; ++i) {
    if (val[i])
      --g[mapp[val[i]] * 2];
  }
  for (int i = 0; i <= P - 2; ++i) {
    ans += mul * (g[i] + g[i + P - 1]) / 2;
    mul = mul * 2 % P;
  }
  cout << ans << endl;
  return 0;
}

Error: TLE

Fixed submission:

#pragma GCC optimize(2)
#include <cstdio>
#include <cstring>
#include <iostream>

#define LL long long
#define Maxn 1600005

using namespace std;

const LL MOD = 998244353, G = 3, P = 200003;

inline LL read() {
  LL x = 0, f = 1;
  char c = getchar();
  while (c < '0' || c > '9') {
    if (c == '-')
      f = -1;
    c = getchar();
  }
  while ('0' <= c && c <= '9') {
    x = x * 10 + c - '0';
    c = getchar();
  }
  return x * f;
}

LL n, m = 1, val[Maxn], mapp[Maxn], f[Maxn], trans[Maxn];

LL Pow(LL a, LL b) {
  LL ans = 1, base = a;
  while (b) {
    if (b & 1)
      ans = ans * base % MOD;
    base = base * base % MOD;
    b >>= 1;
  }
  return ans;
}
const LL invG = Pow(G, MOD - 2);

void NTT(LL *F, bool op) {
  for (int i = 0; i < m; ++i)
    trans[i] = (trans[i >> 1] >> 1) | ((i & 1) ? m >> 1 : 0);
  for (int i = 0; i < m; ++i)
    if (i < trans[i])
      swap(F[i], F[trans[i]]);
  for (int len = 2; len <= m; len <<= 1) {
    LL base = op ? Pow(invG, (MOD - 1) / len) : Pow(G, (MOD - 1) / len);
    for (int i = 0; i < m; i += len) {
      LL now = 1;
      for (int k = i; k < i + (len >> 1); ++k) {
        LL temp = now * F[k + (len >> 1)] % MOD;
        F[k + (len >> 1)] = (F[k] - temp) % MOD;
        F[k] = (F[k] + temp) % MOD;
        now = now * base % MOD;
      }
    }
  }
}

int main() {
  freopen("data.in", "r", stdin);
  freopen("data.out", "w", stdout);
  n = read();
  for (int i = 1; i <= n; ++i)
    val[i] = read();
  LL mul = 1;
  for (int i = 0; i <= P - 2; ++i) {
    mapp[mul] = i;
    mul = mul * 2 % P;
  }
  for (int i = 1; i <= n; ++i)
    if (val[i])
      ++f[mapp[val[i]]];
  while (m < 2 * P - 3)
    m <<= 1;
  // cout << m << endl;
  NTT(f, 0);
  for (int i = 0; i < m; ++i)
    f[i] = f[i] * f[i] % MOD;
  NTT(f, 1);
  for (int i = 0; i < m; ++i)
    f[i] = f[i] * Pow(m, MOD - 2) % MOD, f[i] = (f[i] % MOD + MOD) % MOD;
  for (int i = 1; i <= n; ++i) {
    // printf("%lld\\n", val[i]);
    if (val[i])
      --f[mapp[val[i]] * 2];
  }
  LL ans = 0;
  mul = 1;
  for (int i = 0; i <= P - 2; ++i) {
    ans += mul * (f[i] + f[i + P - 1]) / 2;
    mul = mul * 2 % P;
  }
  cout << ans << endl;
  return 0;
}