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

#include <iostream>
#include <vector>

using namespace std;

long long gcd(long long a, long long b) {
  if (a == 0) {
    return b;
  }
  if (b == 0) {
    return a;
  }

  if (a > b) {
    return gcd(b, a % b);
  }

  return gcd(a, b % a);
}

long long lcm(long long a, long long b) { return a / gcd(a, b) * b; }

vector<int> G; // i --> G[i] Graph

vector<bool> visited;

vector<vector<int>> cycles;

void rec(int p) {
  visited[p] = true;

  cycles.back().push_back(p);

  if (!visited[G[p]]) {
    rec(G[p]);
  }
}

int extgcd(int a, int b, int &x, int &y) {
  int d = a;

  if (b != 0) {
    d = extgcd(b, a % b, y, x);

    y -= (a / b) * x;
  } else {
    x = 1;
    y = 0;
  }

  return d;
}

int modinv(int a) {
  int x, y;

  extgcd(a, 1000000007, x, y);

  return (1000000007 + x % 1000000007) % 1000000007;
}

int main() {
  int V, Q;

  scanf("%d", &V);
  scanf("%d", &Q);

  G = vector<int>(V);

  for (int i = 0; i < V; i++) {
    scanf("%d", &G[i]);
    G[i]--; // 1 -> 0 indexed
  }

  visited = vector<bool>(V, false);

  for (int i = 0; i < V; i++) {
    if (!visited[i]) {
      cycles.push_back(vector<int>());

      rec(i);
    }
  }

  vector<int> val(V, 0), num(V, 0);

  for (int i = 0; i < cycles.size(); i++) {
    int sum = 0;

    for (int j = 0; j < cycles[i].size(); j++) {
      sum += cycles[i][j] + 1;
    }

    for (int j = 0; j < cycles[i].size(); j++) {
      val[cycles[i][j]] = sum;

      num[cycles[i][j]] = cycles[i].size();
    }
  }

  vector<vector<int>> sum(V, vector<int>(41));

  sum[0][num[0]] = 1;

  for (int i = 1; i < V; i++) {
    sum[i][num[i]] = 1;

    for (int j = 1; j <= 40; j++) {
      sum[i][j] += sum[i - 1][j];
    }
  }

  vector<int> sum2(V);

  sum2[0] = (1LL * modinv(num[0]) * val[0]) % 1000000007;

  for (int i = 1; i < V; i++) {
    sum2[i] = (sum2[i - 1] + 1LL * modinv(num[i]) * val[i]) % 1000000007;
  }

  int l, r;

  for (int i = 0; i < Q; i++) {
    scanf("%d", &l);
    l--; // 1 -> 0 indexed
    scanf("%d", &r);
    r--;

    long long rep = 1;
    int c;

    for (int i = 2; i <= 40; i++) {
      c = sum[r][i];

      if (l != 0) {
        c -= sum[l - 1][i];
      }

      if (c != 0) {
        rep = lcm(rep, i);
      }
    }

    int ret = sum2[r] + 1000000007;

    if (l != 0) {
      ret -= sum2[l - 1];
    }

    ret %= 1000000007;

    ret = 1LL * rep % 1000000007 * ret % 1000000007;

    printf("%d\\n", ret);
  }

  return 0;
}

Error: TLE

Fixed submission:

#include <iostream>
#include <vector>

using namespace std;

long long gcd(long long a, long long b) {
  if (a == 0) {
    return b;
  }
  if (b == 0) {
    return a;
  }

  if (a > b) {
    return gcd(b, a % b);
  }

  return gcd(a, b % a);
}

long long lcm(long long a, long long b) { return a / gcd(a, b) * b; }

vector<int> G; // i --> G[i] Graph

vector<bool> visited;

vector<vector<int>> cycles;

void rec(int p) {
  visited[p] = true;

  cycles.back().push_back(p);

  if (!visited[G[p]]) {
    rec(G[p]);
  }
}

int extgcd(int a, int b, int &x, int &y) {
  int d = a;

  if (b != 0) {
    d = extgcd(b, a % b, y, x);

    y -= (a / b) * x;
  } else {
    x = 1;
    y = 0;
  }

  return d;
}

int modinv(int a) {
  int x, y;

  extgcd(a, 1000000007, x, y);

  return (1000000007 + x % 1000000007) % 1000000007;
}

int main() {
  int V, Q;

  scanf("%d", &V);
  scanf("%d", &Q);

  G = vector<int>(V);

  for (int i = 0; i < V; i++) {
    scanf("%d", &G[i]);
    G[i]--; // 1 -> 0 indexed
  }

  visited = vector<bool>(V, false);

  for (int i = 0; i < V; i++) {
    if (!visited[i]) {
      cycles.push_back(vector<int>());

      rec(i);
    }
  }

  vector<int> val(V, 0), num(V, 0);

  for (int i = 0; i < cycles.size(); i++) {
    int sum = 0;

    for (int j = 0; j < cycles[i].size(); j++) {
      sum += cycles[i][j] + 1;
    }

    for (int j = 0; j < cycles[i].size(); j++) {
      val[cycles[i][j]] = sum;

      num[cycles[i][j]] = cycles[i].size();
    }
  }

  vector<vector<int>> sum(V, vector<int>(41));

  sum[0][num[0]] = 1;

  for (int i = 1; i < V; i++) {
    sum[i][num[i]] = 1;

    for (int j = 1; j <= 40; j++) {
      sum[i][j] += sum[i - 1][j];
    }
  }

  int l, r;

  for (int i = 0; i < Q; i++) {
    scanf("%d", &l);
    l--; // 1 -> 0 indexed
    scanf("%d", &r);
    r--;

    long long rep = 1;
    int c;

    for (int i = 2; i <= 40; i++) {
      c = sum[r][i];

      if (l != 0) {
        c -= sum[l - 1][i];
      }

      if (c != 0) {
        rep = lcm(rep, i);
      }
    }

    int ret = 0;

    for (int j = l; j <= r; j++) {
      ret = (ret + rep * modinv(num[j]) % 1000000007 * val[j]) % 1000000007;
    }

    printf("%d\\n", ret);
  }

  return 0;
}