ZS the Coder and Chris the Baboon has explored Udayland for quite some time. They realize that it consists of n towns numbered from 1 to n. There are n directed roads in the Udayland. i-th of them goes from town i to some other town ai (ai ≠ i). ZS the Coder can flip the direction of any road in Udayland, i.e. if it goes from town A to town B before the flip, it will go from town B to town A after.ZS the Coder considers the roads in the Udayland confusing, if there is a sequence of distinct towns A1, A2, ..., Ak (k > 1) such that for every 1 ≤ i < k there is a road from town Ai to town Ai + 1 and another road from town Ak to town A1. In other words, the roads are confusing if some of them form a directed cycle of some towns.Now ZS the Coder wonders how many sets of roads (there are 2n variants) in initial configuration can he choose to flip such that after flipping each road in the set exactly once, the resulting network will not be confusing.Note that it is allowed that after the flipping there are more than one directed road from some town and possibly some towns with no roads leading out of it, or multiple roads between any pair of cities.

The first line of the input contains single integer n (2 ≤ n ≤ 2·105) — the number of towns in Udayland. The next line contains n integers a1, a2, ..., an (1 ≤ ai ≤ n, ai ≠ i), ai denotes a road going from town i to town ai.

Print a single integer — the number of ways to flip some set of the roads so that the resulting whole set of all roads is not confusing. Since this number may be too large, print the answer modulo 109 + 7.

NoteConsider the first sample case. There are 3 towns and 3 roads. The towns are numbered from 1 to 3 and the roads are , ,  initially. Number the roads 1 to 3 in this order. The sets of roads that ZS the Coder can flip (to make them not confusing) are {1}, {2}, {3}, {1, 2}, {1, 3}, {2, 3}. Note that the empty set is invalid because if no roads are flipped, then towns 1, 2, 3 is form a directed cycle, so it is confusing. Similarly, flipping all roads is confusing too. Thus, there are a total of 6 possible sets ZS the Coder can flip.The sample image shows all possible ways of orienting the roads from the first sample such that the network is not confusing.

import core.bitop, std.bitmanip;
import core.checkedint;
import std.algorithm, std.functional;
import std.array, std.container;
import std.bigint;
import std.conv;
import std.math, std.numeric;
import std.range, std.range.interfaces;
import std.stdio, std.string;
import std.typecons;

void main()
{
    int n;
    readf("%s", &n);
    readln;

    auto arr = [0] ~ readln.chomp.split.map!(to!int).array;

    int[] cyclesSizes;
    int t = 1;
    auto tm = new int[] (n+1);

    void dfs(int v, int starttm) {
        tm[v] = t++;
        int u = arr[v];
        if (tm[u] == 0) { dfs(u, starttm); }
        else if (tm[u] >= starttm) { cyclesSizes ~= tm[v] - tm[u] + 1; }
    }

    foreach (i; 1 .. n+1) {
        if (tm[i] != 0) { continue; }

        debug { tm.writeln; }

        dfs(i, t);
    }

    immutable int MD = 10 ^^ 9 + 7;

    auto pws = recurrence!((a, n) => a[n-1] * 2 % MD)(1).take(n+1).array;

    int cycleOpts(int sz) {
        return (pws[sz] - 2 + MD) % MD;
    }

    debug { cyclesSizes.writeln; }

    int ans = cyclesSizes.fold!((ans, nxt) => (ans.to!long * cycleOpts(nxt) % MD).to!int)(1);

    auto rest = n - cyclesSizes.sum;

    ans = ans.to!long * pws[rest] % MD;

    ans.writeln;
}

import std.stdio;
import std.uni;
import std.conv;
import std.container;
import std.functional;
import std.algorithm;
import std.array;
import std.typecons;

enum prime = 1_000_000_000 + 7;
long pmod(long a)
{
  pragma(inline, true);
  return (a%prime + prime)%prime;
}
long pow(long base, long exp)
{
  if (exp == 0)
    return 1;
  base %= prime;
  if (exp % 2 == 0)
    {
      auto pres = pow(base, exp / 2);
      return (pres * pres) % prime;
    }
  return (pow(base, exp - 1) * base) % prime;
}

void main(string[] args)
{
  debug stdin = File(args[1]);
  auto n = next!int;
  auto a = new int[](n);
  a[] = next!int(n)[] - 1;
  auto depth = new int[](n);
  auto neis = new int[][](n);
  auto visited = new bool[](n);
  int[int[2]] edgecount;
  foreach(i, ai; a)
    {
      neis[i] ~= ai;
      neis[ai] ~= cast(int) i;
      edgecount.require([min(cast(int)i, ai), max(cast(int)i, ai)], 0)++;
    }
  auto cyclelen = int(0);
  auto count = int(0);
  bool foundCycle = false;
  void dfs(int node, int depthtoput, int parent)
  {
    debug writeln("visiting ", node, " ", parent);
    count++;
    depth[node] = depthtoput;
    visited[node] = true;
    foreach(nei; neis[node])
      if (edgecount[[min(node, nei), max(node, nei)]] > 0)
        {
          edgecount[[min(node, nei), max(node, nei)]]--;
          debug writeln(node, " -> ", nei);
          if (visited[nei])
            {
              if (!foundCycle)
                {
                  assert(depth[nei] < depth[node], text("found cycle with ", nei, " ", node));
                  cyclelen = depth[node] - depth[nei] + 1;
                  foundCycle = true;
                }
              continue;
            }
          dfs(nei, depthtoput + 1, node);
        }
  }
  long ans = 1;
  foreach(i; 0 .. n)
    {
      if (!visited[i])
        {
          cyclelen = 0;
          count = 0;
          foundCycle = false;
          dfs(i, 0, -1);
          assert(count >= cyclelen);
          auto notincycle = count - cyclelen;
          auto rc = pow(2, cyclelen) - 2;
          auto rn = pow(2, notincycle);
          auto r = pmod(rc * rn);
          ans = pmod(ans * r);
        }
    }
  ans.writeln;
}

// INPUT

enum InputStyle
  {
    byChunk, byLine
  };
enum inputStyle = InputStyle.byLine;

string popWord();
static if (inputStyle == InputStyle.byChunk)
  {
    const chunkSize = 1024 * 1024 * 8;
    const wordSize = 4096;
    char[chunkSize] chunkBuff;
    char[] currChunk;
    void renewChunk()
    {
      if (stdin.eof)
        currChunk = null;
      else
        currChunk = stdin.rawRead(chunkBuff);
    }
    char[wordSize] wordBuff;
    char[] word;
    string popWord()
    {
      if (currChunk.length == 0)
        renewChunk;
      assert(currChunk.length > 0);
      while (currChunk[0].isWhite)
        {

          currChunk = currChunk[1 .. $];
          if (currChunk.length == 0)
            renewChunk;
        }
      word = wordBuff[0 .. 0];
      while (!currChunk[0].isWhite)
        {
          word.length++;
          word[$ - 1] = currChunk[0];
          currChunk = currChunk[1 .. $];
          if (currChunk.length == 0)
            {
              renewChunk;
              if (currChunk.length == 0)
                return cast(string) word;
            }
        }
      return cast(string) word;
    }
  }
 else
   {
     DList!string _words;
     string popWord()
     {
       while (_words.empty)
         {
           foreach(w; stdin.readln.split)
             {
               _words.insertBack(w);
             }
         }
       auto word = _words.front;
       _words.removeFront;
       return word;
     }
   }
T next(T)()
{
  return to!T(popWord);
}
auto next(T, S...)(S s)
{
  static if (S.length == 0)
    {
      return to!T(popWord);
    }
  else
    {
      auto res = new typeof(next!T(s[1 .. $]))[](cast(size_t)s[0]);
      foreach(ref elem; res)
        elem = next!T(s[1 .. $]);
      return res;
    }
}

import std.stdio;
import std.uni;
import std.conv;
import std.container;
import std.functional;
import std.algorithm;
import std.array;
import std.typecons;

enum prime = 1_000_000_000 + 7;
long pmod(long a)
{
  return (a%prime + prime)%prime;
}
long pow(long base, long exp)
{
  if (exp == 0)
    return 1;
  base %= prime;
  if (exp % 2 == 0)
    {
      auto pres = pow(base, exp / 2);
      return (pres * pres) % prime;
    }
  return (pow(base, exp - 1) * base) % prime;
}

void main(string[] args)
{
  debug stdin = File(args[1]);
  auto n = next!int;
  auto a = next!int(n);
  a[] -= 1;
  auto depth = new int[](n);
  auto neis = new int[][](n);
  auto visited = new bool[](n);
  int[int[2]] edgecount;
  foreach(i, ai; a)
    {
      neis[i] ~= ai;
      neis[ai] ~= cast(int) i;
      edgecount.require([min(cast(int)i, ai), max(cast(int)i, ai)], 0)++;
    }
  auto cyclelen = int(0);
  auto count = int(0);
  bool foundCycle = false;
  void dfs(int node, int depthtoput, int parent)
  {
    debug writeln("visiting ", node, " ", parent);
    count++;
    depth[node] = depthtoput;
    visited[node] = true;
    foreach(nei; neis[node])
      if (edgecount[[min(node, nei), max(node, nei)]] > 0)
        {
          edgecount[[min(node, nei), max(node, nei)]]--;
          debug writeln(node, " -> ", nei);
          if (visited[nei])
            {
              if (!foundCycle)
                {
                  assert(depth[nei] < depth[node], text("found cycle with ", nei, " ", node));
                  cyclelen = depth[node] - depth[nei] + 1;
                  foundCycle = true;
                }
              continue;
            }
          dfs(nei, depthtoput + 1, node);
        }
  }
  long ans = 1;
  foreach(i; 0 .. n)
    {
      if (!visited[i])
        {
          cyclelen = 0;
          count = 0;
          foundCycle = false;
          dfs(i, 0, -1);
          assert(count >= cyclelen);
          auto notincycle = count - cyclelen;
          auto rc = pow(2, cyclelen) - 2;
          auto rn = pow(2, notincycle);
          auto r = pmod(rc * rn);
          ans = pmod(ans * r);
        }
    }
  ans.writeln;
}

// INPUT

enum InputStyle
  {
    byChunk, byLine
  };
enum inputStyle = InputStyle.byLine;

string popWord();
static if (inputStyle == InputStyle.byChunk)
  {
    const chunkSize = 1024 * 1024 * 8;
    const wordSize = 4096;
    char[chunkSize] chunkBuff;
    char[] currChunk;
    void renewChunk()
    {
      if (stdin.eof)
        currChunk = null;
      else
        currChunk = stdin.rawRead(chunkBuff);
    }
    char[wordSize] wordBuff;
    char[] word;
    string popWord()
    {
      if (currChunk.length == 0)
        renewChunk;
      assert(currChunk.length > 0);
      while (currChunk[0].isWhite)
        {

          currChunk = currChunk[1 .. $];
          if (currChunk.length == 0)
            renewChunk;
        }
      word = wordBuff[0 .. 0];
      while (!currChunk[0].isWhite)
        {
          word.length++;
          word[$ - 1] = currChunk[0];
          currChunk = currChunk[1 .. $];
          if (currChunk.length == 0)
            {
              renewChunk;
              if (currChunk.length == 0)
                return cast(string) word;
            }
        }
      return cast(string) word;
    }
  }
 else
   {
     DList!string _words;
     string popWord()
     {
       while (_words.empty)
         {
           foreach(w; stdin.readln.split)
             {
               _words.insertBack(w);
             }
         }
       auto word = _words.front;
       _words.removeFront;
       return word;
     }
   }
T next(T)()
{
  return to!T(popWord);
}
auto next(T, S...)(S s)
{
  static if (S.length == 0)
    {
      return to!T(popWord);
    }
  else
    {
      auto res = new typeof(next!T(s[1 .. $]))[](cast(size_t)s[0]);
      foreach(ref elem; res)
        elem = next!T(s[1 .. $]);
      return res;
    }
}

import std.stdio;
import std.uni;
import std.conv;
import std.container;
import std.functional;
import std.algorithm;
import std.array;
import std.typecons;

enum prime = 1_000_000_000 + 7;
long pmod(long a)
{
  pragma(inline, true);
  return (a%prime + prime)%prime;
}
long pow(long base, long exp)
{
  pragma(inline, true);
  base %= prime;
  auto acc = long(1);
  while(exp)
    {
      if (exp & 1) acc = (acc * base) % prime;
      exp = exp >> 1;
      base = (base * base) % prime;
    }
  return acc;
}

void main(string[] args)
{
  debug stdin = File(args[1]);
  auto n = next!int;
  auto a = new int[](n);
  a[] = next!int(n)[] - 1;
  auto depth = new int[](n);
  auto neis = new int[][](n);
  auto visited = new bool[](n);
  int[int[2]] edgecount;
  foreach(i, ai; a)
    {
      neis[i] ~= ai;
      neis[ai] ~= cast(int) i;
      edgecount.require([min(cast(int)i, ai), max(cast(int)i, ai)], 0)++;
    }
  auto cyclelen = int(0);
  auto count = int(0);
  bool foundCycle = false;
  void dfs(int node, int depthtoput, int parent)
  {
    debug writeln("visiting ", node, " ", parent);
    count++;
    depth[node] = depthtoput;
    visited[node] = true;
    foreach(nei; neis[node])
      if (edgecount[[min(node, nei), max(node, nei)]] > 0)
        {
          edgecount[[min(node, nei), max(node, nei)]]--;
          debug writeln(node, " -> ", nei);
          if (visited[nei])
            {
              if (!foundCycle)
                {
                  assert(depth[nei] < depth[node], text("found cycle with ", nei, " ", node));
                  cyclelen = depth[node] - depth[nei] + 1;
                  foundCycle = true;
                }
              continue;
            }
          dfs(nei, depthtoput + 1, node);
        }
  }
  long ans = 1;
  foreach(i; 0 .. n)
    {
      if (!visited[i])
        {
          cyclelen = 0;
          count = 0;
          foundCycle = false;
          dfs(i, 0, -1);
          assert(count >= cyclelen);
          auto notincycle = count - cyclelen;
          auto rc = pow(2, cyclelen) - 2;
          auto rn = pow(2, notincycle);
          auto r = pmod(rc * rn);
          ans = pmod(ans * r);
        }
    }
  ans.writeln;
}

// INPUT

enum InputStyle
  {
    byChunk, byLine
  };
enum inputStyle = InputStyle.byLine;

string popWord();
static if (inputStyle == InputStyle.byChunk)
  {
    const chunkSize = 1024 * 1024 * 8;
    const wordSize = 4096;
    char[chunkSize] chunkBuff;
    char[] currChunk;
    void renewChunk()
    {
      if (stdin.eof)
        currChunk = null;
      else
        currChunk = stdin.rawRead(chunkBuff);
    }
    char[wordSize] wordBuff;
    char[] word;
    string popWord()
    {
      if (currChunk.length == 0)
        renewChunk;
      assert(currChunk.length > 0);
      while (currChunk[0].isWhite)
        {

          currChunk = currChunk[1 .. $];
          if (currChunk.length == 0)
            renewChunk;
        }
      word = wordBuff[0 .. 0];
      while (!currChunk[0].isWhite)
        {
          word.length++;
          word[$ - 1] = currChunk[0];
          currChunk = currChunk[1 .. $];
          if (currChunk.length == 0)
            {
              renewChunk;
              if (currChunk.length == 0)
                return cast(string) word;
            }
        }
      return cast(string) word;
    }
  }
 else
   {
     DList!string _words;
     string popWord()
     {
       pragma(inline, true);
       while (_words.empty)
         {
           foreach(w; stdin.readln.split)
             {
               _words.insertBack(w);
             }
         }
       auto word = _words.front;
       _words.removeFront;
       return word;
     }
   }
T next(T)()
{
  pragma(inline, true);
  return to!T(popWord);
}
auto next(T, S...)(S s)
{
  static if (S.length == 0)
    {
      return to!T(popWord);
    }
  else
    {
      auto res = new typeof(next!T(s[1 .. $]))[](cast(size_t)s[0]);
      foreach(ref elem; res)
        elem = next!T(s[1 .. $]);
      return res;
    }
}

import std.stdio;
import std.uni;
import std.conv;
import std.container;
import std.functional;
import std.algorithm;
import std.array;
import std.typecons;

enum prime = 1_000_000_000 + 7;
long pmod(long a)
{
  pragma(inline, true);
  return (a%prime + prime)%prime;
}
long pow(long base, long exp)
{
  pragma(inline, true);
  base %= prime;
  auto acc = long(1);
  while(exp)
    {
      if (exp & 1) acc = (acc * base) % prime;
      exp = exp >> 1;
      base = (base * base) % prime;
    }
  return acc;
}

void main(string[] args)
{
  debug stdin = File(args[1]);
  auto n = next!int;
  auto a = new int[](n);
  a[] = next!int(n)[] - 1;
  auto depth = new int[](n);
  auto neis = new int[][](n);
  auto visited = new bool[](n);
  int[int[2]] edgecount;
  foreach(i, ai; a)
    {
      neis[i] ~= ai;
      neis[ai] ~= cast(int) i;
      edgecount.require([min(cast(int)i, ai), max(cast(int)i, ai)], 0)++;
    }
  auto cyclelen = int(0);
  auto count = int(0);
  bool foundCycle = false;
  void dfs(int node, int depthtoput, int parent)
  {
    debug writeln("visiting ", node, " ", parent);
    count++;
    depth[node] = depthtoput;
    visited[node] = true;
    foreach(nei; neis[node])
      if (edgecount[[min(node, nei), max(node, nei)]] > 0)
        {
          edgecount[[min(node, nei), max(node, nei)]]--;
          debug writeln(node, " -> ", nei);
          if (visited[nei])
            {
              if (!foundCycle)
                {
                  assert(depth[nei] < depth[node], text("found cycle with ", nei, " ", node));
                  cyclelen = depth[node] - depth[nei] + 1;
                  foundCycle = true;
                }
              continue;
            }
          dfs(nei, depthtoput + 1, node);
        }
  }
  long ans = 1;
  foreach(i; 0 .. n)
    {
      if (!visited[i])
        {
          cyclelen = 0;
          count = 0;
          foundCycle = false;
          dfs(i, 0, -1);
          assert(count >= cyclelen);
          auto notincycle = count - cyclelen;
          auto rc = pow(2, cyclelen) - 2;
          auto rn = pow(2, notincycle);
          auto r = pmod(rc * rn);
          ans = pmod(ans * r);
        }
    }
  ans.writeln;
}

// INPUT

enum InputStyle
  {
    byChunk, byLine
  };
enum inputStyle = InputStyle.byLine;

string popWord();
static if (inputStyle == InputStyle.byChunk)
  {
    const chunkSize = 1024 * 1024 * 8;
    const wordSize = 4096;
    char[chunkSize] chunkBuff;
    char[] currChunk;
    void renewChunk()
    {
      if (stdin.eof)
        currChunk = null;
      else
        currChunk = stdin.rawRead(chunkBuff);
    }
    char[wordSize] wordBuff;
    char[] word;
    string popWord()
    {
      if (currChunk.length == 0)
        renewChunk;
      assert(currChunk.length > 0);
      while (currChunk[0].isWhite)
        {

          currChunk = currChunk[1 .. $];
          if (currChunk.length == 0)
            renewChunk;
        }
      word = wordBuff[0 .. 0];
      while (!currChunk[0].isWhite)
        {
          word.length++;
          word[$ - 1] = currChunk[0];
          currChunk = currChunk[1 .. $];
          if (currChunk.length == 0)
            {
              renewChunk;
              if (currChunk.length == 0)
                return cast(string) word;
            }
        }
      return cast(string) word;
    }
  }
 else
   {
     DList!string _words;
     string popWord()
     {
       while (_words.empty)
         {
           foreach(w; stdin.readln.split)
             {
               _words.insertBack(w);
             }
         }
       auto word = _words.front;
       _words.removeFront;
       return word;
     }
   }
T next(T)()
{
  return to!T(popWord);
}
auto next(T, S...)(S s)
{
  static if (S.length == 0)
    {
      return to!T(popWord);
    }
  else
    {
      auto res = new typeof(next!T(s[1 .. $]))[](cast(size_t)s[0]);
      foreach(ref elem; res)
        elem = next!T(s[1 .. $]);
      return res;
    }
}

import core.bitop, std.bitmanip;
import core.checkedint;
import std.algorithm, std.functional;
import std.array, std.container;
import std.bigint;
import std.conv;
import std.math, std.numeric;
import std.range, std.range.interfaces;
import std.stdio, std.string;
import std.typecons;

void main()
{
    int n;
    readf("%s", &n);
    readln;

    auto arr = [0] ~ readln.chomp.split.map!(to!int).array;

    int[] cycleSzs;

    auto g = new int[][] (n+1);
    foreach (i, e; arr.dropOne.enumerate(1)) {
        if (arr[e] == i) {
            if (i < e) { cycleSzs ~= 2; }
        } else {
            g[i] ~= e;
            g[e] ~= i;
        }
    }

    debug { g.writeln; }

    int t = 1;
    auto tm = new int[] (n+1);
    auto isOut = new bool[] (n+1);

    void dfs(int v, int fr) {
        tm[v] = t++;
        foreach (u; g[v]) {
            if (u == fr) { continue; }

            if (tm[u] != 0 && isOut[u]) { continue; }

            if (tm[u] != 0 && !isOut[u]) {
                isOut[v] = true;
                cycleSzs ~= tm[v] - tm[u] + 1;
                return;
            }

            dfs(u, v);
        }

        isOut[v] = true;
    }

    foreach (i; 1 .. n+1) {
        if (tm[i] != 0) { continue; }

        dfs(i, -1);
    }

    immutable int MD = 10 ^^ 9 + 7;

    auto pws = recurrence!((a, n) => a[n-1] * 2 % MD)(1).take(n+1).array;

    int cycleOpts(int sz) {
        return (pws[sz] - 2 + MD) % MD;
    }

    debug { cycleSzs.writeln; }

    int ans = cycleSzs.fold!((ans, nxt) => (ans.to!long * cycleOpts(nxt) % MD).to!int)(1);

    auto rest = n - cycleSzs.sum;

    ans = ans.to!long * pws[rest] % MD;

    ans.writeln;
}

import core.bitop, std.bitmanip;
import core.checkedint;
import std.algorithm, std.functional;
import std.array, std.container;
import std.bigint;
import std.conv;
import std.math, std.numeric;
import std.range, std.range.interfaces;
import std.stdio, std.string;
import std.typecons;

void main()
{
    int n;
    readf("%s", &n);
    readln;

    auto arr = [0] ~ readln.chomp.split.map!(to!int).array;

    int[] cycleSzs;

    auto g = new int[][] (n+1);
    foreach (i, e; arr.dropOne.enumerate(1)) {
        if (arr[e] == i) {
            if (i < e) { cycleSzs ~= 2; }
        } else {
            g[i] ~= e;
            g[e] ~= i;
        }
    }

    debug { g.writeln; }

    int t = 1;
    auto tm = new int[] (n+1);
    auto isOut = new bool[] (n+1);

    void dfs(int v, int fr) {
        tm[v] = t++;
        foreach (u; g[v]) {
            if (u == fr) { continue; }

            if (tm[u] != 0 && isOut[u]) { continue; }

            if (tm[u] != 0 && !isOut[u]) {
                isOut[v] = true;
                cycleSzs ~= tm[v] - tm[u] + 1;
                return;
            }

            dfs(u, v);
        }

        isOut[v] = true;
    }

    foreach (i; 1 .. n+1) {
        if (tm[i] != 0) { continue; }

        dfs(i, -1);
    }

    immutable int MD = 10 ^^ 9 + 7;

    auto pws = recurrence!((a, n) => a[n-1] * 2 % MD)(1).take(n+1).array;

    int cycleOpts(int sz) {
        return (pws[sz] - 2 + MD) % MD;
    }

    debug { cycleSzs.writeln; }

    int ans = cycleSzs.fold!((ans, nxt) => ans * cycleOpts(nxt) % MD)(1);

    auto rest = n - cycleSzs.sum;

    ans = ans.to!long * pws[rest] % MD;

    ans.writeln;
}

import std.stdio;
import std.uni;
import std.conv;
import std.container;
import std.functional;
import std.algorithm;
import std.array;
import std.typecons;

enum prime = 1_000_000 + 7;
long pmod(long a)
{
  return (a%prime + prime)%prime;
}
long pow(long base, long exp)
{
  if (exp == 0)
    return 1;
  base %= prime;
  if (exp % 2 == 0)
    {
      auto pres = pow(base, exp / 2);
      return (pres * pres) % prime;
    }
  return (pow(base, exp - 1) * base) % prime;
}

void main(string[] args)
{
  debug stdin = File(args[1]);
  auto n = next!int;
  auto a = next!int(n);
  a[] -= 1;
  auto depth = new int[](n);
  auto neis = new int[][](n);
  auto visited = new bool[](n);
  int[int[2]] edgecount;
  foreach(i, ai; a)
    {
      neis[i] ~= ai;
      neis[ai] ~= cast(int) i;
      edgecount.require([min(cast(int)i, ai), max(cast(int)i, ai)], 0)++;
    }
  auto cyclelen = int(0);
  auto count = int(0);
  bool foundCycle = false;
  void dfs(int node, int depthtoput, int parent)
  {
    debug writeln("visiting ", node, " ", parent);
    count++;
    depth[node] = depthtoput;
    visited[node] = true;
    foreach(nei; neis[node])
      if (edgecount[[min(node, nei), max(node, nei)]] > 0)
        {
          edgecount[[min(node, nei), max(node, nei)]]--;
          debug writeln(node, " -> ", nei);
          if (visited[nei])
            {
              if (!foundCycle)
                {
                  assert(depth[nei] < depth[node], text("found cycle with ", nei, " ", node));
                  cyclelen = depth[node] - depth[nei] + 1;
                  foundCycle = true;
                }
              continue;
            }
          dfs(nei, depthtoput + 1, node);
        }
  }
  long ans = 1;
  foreach(i; 0 .. n)
    {
      if (!visited[i])
        {
          cyclelen = 0;
          count = 0;
          foundCycle = false;
          dfs(i, 0, -1);
          assert(count >= cyclelen);
          auto notincycle = count - cyclelen;
          auto rc = pow(2, cyclelen) - 2;
          auto rn = pow(2, notincycle);
          auto r = pmod(rc * rn);
          ans = pmod(ans * r);
        }
    }
  ans.writeln;
}

// INPUT

enum InputStyle
  {
    byChunk, byLine
  };
enum inputStyle = InputStyle.byLine;

string popWord();
static if (inputStyle == InputStyle.byChunk)
  {
    const chunkSize = 1024 * 1024 * 8;
    const wordSize = 4096;
    char[chunkSize] chunkBuff;
    char[] currChunk;
    void renewChunk()
    {
      if (stdin.eof)
        currChunk = null;
      else
        currChunk = stdin.rawRead(chunkBuff);
    }
    char[wordSize] wordBuff;
    char[] word;
    string popWord()
    {
      if (currChunk.length == 0)
        renewChunk;
      assert(currChunk.length > 0);
      while (currChunk[0].isWhite)
        {

          currChunk = currChunk[1 .. $];
          if (currChunk.length == 0)
            renewChunk;
        }
      word = wordBuff[0 .. 0];
      while (!currChunk[0].isWhite)
        {
          word.length++;
          word[$ - 1] = currChunk[0];
          currChunk = currChunk[1 .. $];
          if (currChunk.length == 0)
            {
              renewChunk;
              if (currChunk.length == 0)
                return cast(string) word;
            }
        }
      return cast(string) word;
    }
  }
 else
   {
     DList!string _words;
     string popWord()
     {
       while (_words.empty)
         {
           foreach(w; stdin.readln.split)
             {
               _words.insertBack(w);
             }
         }
       auto word = _words.front;
       _words.removeFront;
       return word;
     }
   }
T next(T)()
{
  return to!T(popWord);
}
auto next(T, S...)(S s)
{
  static if (S.length == 0)
    {
      return to!T(popWord);
    }
  else
    {
      auto res = new typeof(next!T(s[1 .. $]))[](cast(size_t)s[0]);
      foreach(ref elem; res)
        elem = next!T(s[1 .. $]);
      return res;
    }
}

import std.stdio;
import std.uni;
import std.conv;
import std.container;
import std.functional;
import std.algorithm;
import std.array;
import std.typecons;

enum prime = 1_000_000_000 + 7;
long pmod(long a)
{
  pragma(inline, true);
  return (a%prime + prime)%prime;
}
long pow(long base, long exp)
{
  pragma(inline, true);
  base %= prime;
  auto p = base;
  auto acc = long(1);
  while(exp)
    {
      if (exp & 1) acc *= p;
      exp = exp >> 1;
      p = (p * p) % prime;
    }
  return acc;
}

void main(string[] args)
{
  debug stdin = File(args[1]);
  auto n = next!int;
  auto a = new int[](n);
  a[] = next!int(n)[] - 1;
  auto depth = new int[](n);
  auto neis = new int[][](n);
  auto visited = new bool[](n);
  int[int[2]] edgecount;
  foreach(i, ai; a)
    {
      neis[i] ~= ai;
      neis[ai] ~= cast(int) i;
      edgecount.require([min(cast(int)i, ai), max(cast(int)i, ai)], 0)++;
    }
  auto cyclelen = int(0);
  auto count = int(0);
  bool foundCycle = false;
  void dfs(int node, int depthtoput, int parent)
  {
    debug writeln("visiting ", node, " ", parent);
    count++;
    depth[node] = depthtoput;
    visited[node] = true;
    foreach(nei; neis[node])
      if (edgecount[[min(node, nei), max(node, nei)]] > 0)
        {
          edgecount[[min(node, nei), max(node, nei)]]--;
          debug writeln(node, " -> ", nei);
          if (visited[nei])
            {
              if (!foundCycle)
                {
                  assert(depth[nei] < depth[node], text("found cycle with ", nei, " ", node));
                  cyclelen = depth[node] - depth[nei] + 1;
                  foundCycle = true;
                }
              continue;
            }
          dfs(nei, depthtoput + 1, node);
        }
  }
  long ans = 1;
  foreach(i; 0 .. n)
    {
      if (!visited[i])
        {
          cyclelen = 0;
          count = 0;
          foundCycle = false;
          dfs(i, 0, -1);
          assert(count >= cyclelen);
          auto notincycle = count - cyclelen;
          auto rc = pow(2, cyclelen) - 2;
          auto rn = pow(2, notincycle);
          auto r = pmod(rc * rn);
          ans = pmod(ans * r);
        }
    }
  ans.writeln;
}

// INPUT

enum InputStyle
  {
    byChunk, byLine
  };
enum inputStyle = InputStyle.byLine;

string popWord();
static if (inputStyle == InputStyle.byChunk)
  {
    const chunkSize = 1024 * 1024 * 8;
    const wordSize = 4096;
    char[chunkSize] chunkBuff;
    char[] currChunk;
    void renewChunk()
    {
      if (stdin.eof)
        currChunk = null;
      else
        currChunk = stdin.rawRead(chunkBuff);
    }
    char[wordSize] wordBuff;
    char[] word;
    string popWord()
    {
      if (currChunk.length == 0)
        renewChunk;
      assert(currChunk.length > 0);
      while (currChunk[0].isWhite)
        {

          currChunk = currChunk[1 .. $];
          if (currChunk.length == 0)
            renewChunk;
        }
      word = wordBuff[0 .. 0];
      while (!currChunk[0].isWhite)
        {
          word.length++;
          word[$ - 1] = currChunk[0];
          currChunk = currChunk[1 .. $];
          if (currChunk.length == 0)
            {
              renewChunk;
              if (currChunk.length == 0)
                return cast(string) word;
            }
        }
      return cast(string) word;
    }
  }
 else
   {
     DList!string _words;
     string popWord()
     {
       while (_words.empty)
         {
           foreach(w; stdin.readln.split)
             {
               _words.insertBack(w);
             }
         }
       auto word = _words.front;
       _words.removeFront;
       return word;
     }
   }
T next(T)()
{
  return to!T(popWord);
}
auto next(T, S...)(S s)
{
  static if (S.length == 0)
    {
      return to!T(popWord);
    }
  else
    {
      auto res = new typeof(next!T(s[1 .. $]))[](cast(size_t)s[0]);
      foreach(ref elem; res)
        elem = next!T(s[1 .. $]);
      return res;
    }
}


You get to work and turn on the computer. You start coding and give little thought to the RAM role in the whole process. In this problem your task is to solve one of the problems you encounter in your computer routine.We'll consider the RAM as a sequence of cells that can contain data. Some cells already contain some data, some are empty. The empty cells form the so-called memory clusters. Thus, a memory cluster is a sequence of some consecutive empty memory cells. You have exactly n memory clusters, the i-th cluster consists of ai cells. You need to find memory for m arrays in your program. The j-th array takes 2bj consecutive memory cells. There possibly isn't enough memory for all m arrays, so your task is to determine what maximum number of arrays can be located in the available memory clusters. Of course, the arrays cannot be divided between the memory clusters. Also, no cell can belong to two arrays.

The first line of the input contains two integers n and m (1 ≤ n, m ≤ 106). The next line contains n integers a1, a2, ..., an (1 ≤ ai ≤ 109). The next line contains m integers b1, b2, ..., bm (1 ≤ 2bi ≤ 109).

Print a single integer — the answer to the problem.

NoteIn the first example you are given memory clusters with sizes 8, 4, 3, 2, 2 and arrays with sizes 8, 4, 4. There are few ways to obtain an answer equals 2: you can locate array with size 8 to the cluster with size 8, and one of the arrays with size 4 to the cluster with size 4. Another way is to locate two arrays with size 4 to the one cluster with size 8.In the second example you are given 10 memory clusters with size 1 and 6 arrays with size 1. You can choose any 6 clusters and locate all given arrays to them.

// Cheese-Cracker: cheese-cracker.github.io
import std.stdio, std.conv, std.functional, std.string, std.algorithm;
import std.container, std.range, std.typecons, std.bigint, std.numeric, std.math, std.random;

alias ll = long;
alias rbt = redBlackTree;
alias tup = Tuple!(long, long);
static string[] inp;
T rd(T = long)(){ while(!inp.length) inp = readln.chomp.split; string res = inp[0]; inp.popFront; return res.to!T; }
T[] rdarr(T = long)(T fix = 0){ auto r = readln.chomp.split.to!(T[]); r[] += fix; return r; }
/*******************************It's a Me, Mario!*******************************************/

ll[] totake, bitclust;

ll fval(ll endm){
    ll[34] freq = 0;
    ll[] memory = bitclust.dup;
    foreach(i; 0..endm.to!int){ ++freq[totake[i].to!int]; }

    foreach_reverse(k; 0..33){
        foreach_reverse(i; 0..k+1){
            ll take = min(freq[i]<<i, memory[k]<<k);
            ll taken = take/(1L<<i);
            freq[i] -= taken;
            ll left = (memory[k]<<k) - (taken << i);
            /* debug if(left)writeln(left, " ", memory[k]<<k, " ", memory[k], " ", k, " ", take); */
            memory[k] = 0;
            bitter(left, memory, k);
        }
        /* debug writeln(memory); */
    }
    /* debug writeln(endm, " ", freq); */
    foreach(i; 0..33){
        if(freq[i]) return 0;
    }
    return 1;
}

// Bit-terness of TLE
void bitter(ll val, ll[] freq, int maxx){
    ll num = val;
    foreach_reverse(i; 0..maxx){
        ll pow = 1<<i;
        freq[i] += num/pow;
        num %= pow;
    }
}

void play(){
    int n, m;
    n = rd!int; m = rd!int;
    ll[] clusters = rdarr;
    totake = rdarr;
    ll takes = 0;

    // Available units from clusters
    totake.sort();
    bitclust.length = 34;
    foreach(el; clusters){
        foreach(i; 0..33){
           if(el & (1L<<i)){
               ++bitclust[i];
           }
        }
    }
    /* writeln(bitclust); */

    // binsearch
    ll lo = 0; ll hi = m + 1;
    while(hi - lo > 1){
        ll midd = (hi + lo)/2;
        (fval(midd) >= 1 ? lo : hi) = midd;
    }
    writeln(lo);
}

int main(){
    long t = 1;
    /* t = rd;        // Toggle! */
    while(t--) play();  // Let's play!
    stdout.flush;
    return 0;
}

// Cheese-Cracker: cheese-cracker.github.io
import std.stdio, std.conv, std.functional, std.string, std.algorithm;
import std.container, std.range, std.typecons, std.bigint, std.numeric, std.math, std.random;

alias ll = long;
alias rbt = redBlackTree;
alias tup = Tuple!(long, long);
static string[] inp;
T rd(T = long)(){ while(!inp.length) inp = readln.chomp.split; string res = inp[0]; inp.popFront; return res.to!T; }
T[] rdarr(T = long)(T fix = 0){ auto r = readln.chomp.split.to!(T[]); r[] += fix; return r; }
/*******************************It's a Me, Mario!*******************************************/

ll[] totake, bitclust;

ll fval(ll endm){
    ll[34] freq = 0;
    ll[] memory = bitclust.dup;
    foreach(i; 0..endm.to!int){ ++freq[totake[i].to!int]; }

    foreach_reverse(k; 0..33){
        foreach_reverse(i; 0..k+1){
            ll take = min(freq[i]<<i, memory[k]<<k);
            ll taken = take/(1L<<i);
            freq[i] -= taken;
            ll left = (memory[k]<<k) - (taken << i);
            /* debug if(left)writeln(left, " ", memory[k]<<k, " ", memory[k], " ", k, " ", take); */
            memory[k] = 0;
            bitter(left, memory, k);
        }
        /* debug writeln(memory); */
    }
    /* debug writeln(endm, " ", freq); */
    foreach(i; 0..33){
        if(freq[i]) return 0;
    }
    return 1;
}

// Bit-terness of TLE
void bitter(ll val, ll[] freq, int maxx){
    ll num = val;
    foreach_reverse(i; 0..maxx){
        ll pow = 1<<i;
        freq[i] += num/pow;
        num %= pow;
    }
}

void play(){
    int n, m;
    n = rd!int; m = rd!int;
    ll[] clusters = rdarr;
    totake = rdarr;
    ll takes = 0;

    // Available units from clusters
    totake.sort();
    bitclust.length = 34;
    foreach(el; clusters){
        foreach(i; 0..33){
           if(el & (1L<<i)){
               ++bitclust[i];
           }
        }
    }
    writeln(bitclust);

    // binsearch
    ll lo = 0; ll hi = m + 1;
    while(hi - lo > 1){
        ll midd = (hi + lo)/2;
        (fval(midd) >= 1 ? lo : hi) = midd;
    }
    writeln(lo);
}

int main(){
    long t = 1;
    /* t = rd;        // Toggle! */
    while(t--) play();  // Let's play!
    stdout.flush;
    return 0;
}

// Cheese-Cracker: cheese-cracker.github.io
import std.stdio, std.conv, std.functional, std.string, std.algorithm;
import std.container, std.range, std.typecons, std.bigint, std.numeric, std.math, std.random;

alias ll = long;
alias rbt = redBlackTree;
alias tup = Tuple!(long, long);
static string[] inp;
T rd(T = long)(){ while(!inp.length) inp = readln.chomp.split; string res = inp[0]; inp.popFront; return res.to!T; }
T[] rdarr(T = long)(T fix = 0){ auto r = readln.chomp.split.to!(T[]); r[] += fix; return r; }
/*******************************It's a Me, Mario!*******************************************/

void play(){
    int n, m;
    n = rd!int; m = rd!int;
    ll[] clusters = rdarr;
    ll[] totake = rdarr;
    ll takes = 0;
    ll[35] freq = 0;

    // Available units from clusters
    ll[35] bitmatch = 0;
    foreach(i; 0..35){
        foreach(cls; clusters){
            if(cls & (1L << i)){
                ++bitmatch[i];
            }
        }
    }

    // Elements
    foreach(el; totake){
        ++freq[el.to!int];
    }
    /* debug writeln(freq, bitmatch); */
    ll res = 0;
    auto setval = rbt!(tup);
    foreach(i; 0..35){
        if(freq[i]) setval.insert(tup(i, freq[i]));
        ll left = bitmatch[i];
        ll pow = (1L << i);
        while(setval.length && left > 0){
            ll plow = setval.front[0];
            ll siz = setval.front[1];
            setval.removeFront;

            ll valu = siz*(1L << plow);
            ll cost = valu/pow + (valu % pow != 0);
            /* writeln(valu, " ", cost); */

            ll take = min(cost, left);
            left -= take;

            ll itemtake = min((take * pow)/(1L << plow), siz);
            /* writeln("DEB: ", cost , " ", take, " ", itemtake); */
            if(siz - itemtake > 0) setval.insert(tup(plow, siz - itemtake));
            res += itemtake;
        }
    }
    writeln(res);
}

int main(){
    long t = 1;
    /* t = rd;        // Toggle! */
    while(t--) play();  // Let's play!
    stdout.flush;
    return 0;
}

// Cheese-Cracker: cheese-cracker.github.io
import std.stdio, std.conv, std.functional, std.string, std.algorithm;
import std.container, std.range, std.typecons, std.bigint, std.numeric, std.math, std.random;

alias ll = long;
alias rbt = redBlackTree;
alias tup = Tuple!(long, long);
static string[] inp;
T rd(T = long)(){ while(!inp.length) inp = readln.chomp.split; string res = inp[0]; inp.popFront; return res.to!T; }
T[] rdarr(T = long)(T fix = 0){ auto r = readln.chomp.split.to!(T[]); r[] += fix; return r; }
/*******************************It's a Me, Mario!*******************************************/

void play(){
    int n, m;
    n = rd!int; m = rd!int;
    ll[] clusters = rdarr;
    ll[] totake = rdarr;

    ll takes = 0; int pos = 0, pos2 = 1;

    ll[] pows;
    foreach(i; 0..35){ pows ~= 2^^i; }

    clusters.sort();
    totake.sort();
    ll cls = clusters[0];
    while( pos < totake.length){
        ll fst = pows[totake[pos].to!int];
        if(fst <= cls){
            cls -= fst;
            ++takes;
            ++pos;
        }else if(pos2 < clusters.length){
            cls = clusters[pos2];
            ++pos2;
        }else{
            break;
        }
        debug writeln(fst, " ", cls);
    }
    writeln(takes);
}

int main(){
    long t = 1;
    /* t = rd;        // Toggle! */
    while(t--) play();  // Let's play!
    stdout.flush;
    return 0;
}

// Cheese-Cracker: cheese-cracker.github.io
import std.stdio, std.conv, std.functional, std.string, std.algorithm;
import std.container, std.range, std.typecons, std.bigint, std.numeric, std.math, std.random;

alias ll = long;
alias rbt = redBlackTree;
alias tup = Tuple!(long, long);
static string[] inp;
T rd(T = long)(){ while(!inp.length) inp = readln.chomp.split; string res = inp[0]; inp.popFront; return res.to!T; }
T[] rdarr(T = long)(T fix = 0){ auto r = readln.chomp.split.to!(T[]); r[] += fix; return r; }
/*******************************It's a Me, Mario!*******************************************/

void play(){
    int n, m;
    n = rd!int; m = rd!int;
    ll[] clusters = rdarr;
    ll[] totake = rdarr;
    ll takes = 0;
    ll[35] freq = 0;

    // Available units from clusters
    ll[35] bitmatch = 0;
    foreach(i; 0..35){
        foreach(cls; clusters){
            if(cls & (1L << i)){
                ++bitmatch[i];
            }
        }
    }

    // Elements
    foreach(el; totake){
        ++freq[el.to!int];
    }
    ll res = 0;
    auto setval = rbt!(tup);
    foreach(i; 0..35){
        if(freq[i]) setval.insert(tup(i, freq[i]));
        ll left = bitmatch[i];
        ll pow = (1L << i);
        bool remseen = 0;
        while(setval.length && left > 0){
            ll plow = setval.front[0];
            ll siz = setval.front[1];
            setval.removeFront;

            ll valu = siz*(1L << plow);
            // Take remainder only if NOT Taken
            ll cost = valu/pow + (!remseen && valu % pow != 0);
            /* writeln(valu, " ", cost); */

            ll take = 0, itemtake = 0;
            if(cost <= left){
                take = cost;
                itemtake += siz;
                if(valu % pow != 0){ remseen = 1; }
            }else{
                take = left;
                // Items can be taken + REM if already taken before
                itemtake = take*pow/(1L<<plow) + (remseen && valu % pow == 0);
            }
            left -= take;

            /* writeln("DEB: ", cost , " ", take, " ", itemtake); */
            if(siz - itemtake > 0) setval.insert(tup(plow, siz - itemtake));
            res += itemtake;
            /* freq[plow] -= itemtake; */
            /* bitmatch[i] = left; */
            /* debug writeln(setval, " ", freq, " ", bitmatch); */
        }
    }
    writeln(res);
}

int main(){
    long t = 1;
    /* t = rd;        // Toggle! */
    while(t--) play();  // Let's play!
    stdout.flush;
    return 0;
}


This is the easy version of the problem. The difference between versions is the constraints on $$$n$$$ and $$$a_i$$$. You can make hacks only if all versions of the problem are solved.First, Aoi came up with the following idea for the competitive programming problem:Yuzu is a girl who collecting candies. Originally, she has $$$x$$$ candies. There are also $$$n$$$ enemies numbered with integers from $$$1$$$ to $$$n$$$. Enemy $$$i$$$ has $$$a_i$$$ candies.Yuzu is going to determine a permutation $$$P$$$. A permutation is an array consisting of $$$n$$$ distinct integers from $$$1$$$ to $$$n$$$ in arbitrary order. For example, $$$\{2,3,1,5,4\}$$$ is a permutation, but $$$\{1,2,2\}$$$ is not a permutation ($$$2$$$ appears twice in the array) and $$$\{1,3,4\}$$$ is also not a permutation (because $$$n=3$$$ but there is the number $$$4$$$ in the array).After that, she will do $$$n$$$ duels with the enemies with the following rules:  If Yuzu has equal or more number of candies than enemy $$$P_i$$$, she wins the duel and gets $$$1$$$ candy. Otherwise, she loses the duel and gets nothing.  The candy which Yuzu gets will be used in the next duels. Yuzu wants to win all duels. How many valid permutations $$$P$$$ exist?This problem was easy and wasn't interesting for Akari, who is a friend of Aoi. And Akari made the following problem from the above idea:Let's define $$$f(x)$$$ as the number of valid permutations for the integer $$$x$$$.You are given $$$n$$$, $$$a$$$ and a prime number $$$p \le n$$$. Let's call a positive integer $$$x$$$ good, if the value $$$f(x)$$$ is not divisible by $$$p$$$. Find all good integers $$$x$$$.Your task is to solve this problem made by Akari.

The first line contains two integers $$$n$$$, $$$p$$$ $$$(2 \le p \le n \le 2000)$$$. It is guaranteed, that the number $$$p$$$ is prime (it has exactly two divisors $$$1$$$ and $$$p$$$). The second line contains $$$n$$$ integers $$$a_1, a_2, \ldots, a_n$$$ $$$(1 \le a_i \le 2000)$$$.

In the first line, print the number of good integers $$$x$$$. In the second line, output all good integers $$$x$$$ in the ascending order. It is guaranteed that the number of good integers $$$x$$$ does not exceed $$$10^5$$$.

NoteIn the first test, $$$p=2$$$.  If $$$x \le 2$$$, there are no valid permutations for Yuzu. So $$$f(x)=0$$$ for all $$$x \le 2$$$. The number $$$0$$$ is divisible by $$$2$$$, so all integers $$$x \leq 2$$$ are not good.  If $$$x = 3$$$, $$$\{1,2,3\}$$$ is the only valid permutation for Yuzu. So $$$f(3)=1$$$, so the number $$$3$$$ is good.  If $$$x = 4$$$, $$$\{1,2,3\} , \{1,3,2\} , \{2,1,3\} , \{2,3,1\}$$$ are all valid permutations for Yuzu. So $$$f(4)=4$$$, so the number $$$4$$$ is not good.  If $$$x \ge 5$$$, all $$$6$$$ permutations are valid for Yuzu. So $$$f(x)=6$$$ for all $$$x \ge 5$$$, so all integers $$$x \ge 5$$$ are not good. So, the only good number is $$$3$$$.In the third test, for all positive integers $$$x$$$ the value $$$f(x)$$$ is divisible by $$$p = 3$$$.

import std.algorithm, std.conv, std.range, std.stdio;
void main () {
	int n, p;
	while (readf !(" %s %s") (n, p) > 0) {
		readln;
		auto a = readln.splitter.map !(to !(int)).array;
		sort (a);
		int [] answer;
		foreach (x; 1..4001) {
			bool ok = true;
			int cur = 0;
			foreach (i; 0..n) {
				while (cur < n && x + i >= a[cur]) {
					cur += 1;
				}
				ok &= !!((cur - i) % p);
			}
			if (ok) {
				answer ~= x;
			}
		}
		writeln (answer.length);
		writefln !("%(%s %)") (answer);
	}
}

import std.stdio, std.conv, std.functional, std.string;
import std.algorithm, std.array, std.container, std.range, std.typecons;
import std.bigint, std.numeric, std.math, std.random;
import core.bitop;

string FMT_F = "%.10f";

static File _f;
void file_io(string fn) { _f = File(fn, "r"); }
static string[] s_rd;
T _RD(T = long)() { while(!s_rd.length) s_rd = readln.chomp.split; string res = s_rd[0]; s_rd.popFront; return res.to!T; }
T _RD(T = long)(File f) { while(!s_rd.length) s_rd = f.readln.chomp.split; string res = s_rd[0]; s_rd.popFront; return res.to!T; }
T[] _RDA(T = long)(T fix = 0) { auto r = readln.chomp.split.to!(T[]); r[] += fix; return r; }
T[] _RDA(T = long)(File f, T fix = 0) { auto r = f.readln.chomp.split.to!(T[]); r[] += fix; return r; }
T RD(T = long)() { if (_f.isOpen) return _RD!T(_f); else return _RD!T; }
T[] RDA(T = long)(T fix = 0) { if (_f.isOpen)  return _RDA!T(_f, fix); else return _RDA!T(fix); }

size_t[] MAKE_IDX(alias less = "a < b", Range)(Range range) { auto idx = new size_t[](range.length); makeIndex!(less)(range, idx); return idx;}
size_t MIN_POS(alias less = "a < b", Range)(Range range) { auto r = minPos!(less)(range); return range.length - r.length; }

void chmin(T)(ref T x, T y) { x = min(x, y); } void chmax(T)(ref T x, T y) { x = max(x, y); }
bool inside(T)(T x, T b, T e) { return x >= b && x < e; }
T lcm(T)(T x, T y) { return x * (y / gcd(x, y)); }

long mod = 10^^9 + 7;
//long mod = 998_244_353;
//long mod = 1_000_003;
void moda(T)(ref T x, T y) { x = (x + y) % mod; }
void mods(T)(ref T x, T y) { x = ((x + mod) - (y % mod)) % mod; }
void modm(T)(ref T x, T y) { x = (x * y) % mod; }
void modpow(T)(ref T x, T y) { if (!y) { x = 1; return; } auto t = x; x.modpow(y>>1); x.modm(x); if (y&1) x.modm(t); }
void modd(T)(ref T x, T y) { y.modpow(mod - 2); x.modm(y); }

void main()
{
	auto n = RD!int;
	auto p = RD!int;
	auto a = RDA!int;
	mod = p;

	int[] ans;
	a.sort();
	foreach (i; 1..a.back+1)
	{
		auto cnt = new int[](n);
		bool ok = true;
		foreach (j; 0..n)
		{
			auto d = max(a[j] - i, 0);
			if (d >= n)
			{
				ok = false;
				break;
			}
			++cnt[d];
		}
		if (!ok) continue;

		long pat = 1;
		long s;
		foreach (j; 0..n)
		{
			s += cnt[j];
			if (s - j <= 0)
			{
				ok = false;
				break;
			}
			pat.modm(s-j);
		}
		if (!ok) continue;
		if (pat != 0)
		{
			ans ~= i;
		}
	}

	writeln(ans.length);
	ans.map!(to!string).join(" ").writeln;

	stdout.flush;
	debug readln;
}

import std.algorithm, std.conv, std.range, std.stdio;
void main () {
	int n, p;
	while (readf !(" %s %s") (n, p) > 0) {
		readln;
		auto a = readln.splitter.map !(to !(int)).array;
		sort (a);
		int [] answer;
		foreach (x; 1..n + 1) {
			bool ok = true;
			int cur = 0;
			foreach (i; 0..n) {
				while (cur < n && x + i >= a[cur]) {
					cur += 1;
				}
				ok &= !!((cur - i) % x);
			}
			if (ok) {
				answer ~= x;
			}
		}
		writeln (answer.length);
		writefln !("%(%s %)") (answer);
	}
}


You are given an undirected connected weighted graph consisting of $$$n$$$ vertices and $$$m$$$ edges. Let's denote the length of the shortest path from vertex $$$1$$$ to vertex $$$i$$$ as $$$d_i$$$. You have to erase some edges of the graph so that at most $$$k$$$ edges remain. Let's call a vertex $$$i$$$ good if there still exists a path from $$$1$$$ to $$$i$$$ with length $$$d_i$$$ after erasing the edges.Your goal is to erase the edges in such a way that the number of good vertices is maximized.

The first line contains three integers $$$n$$$, $$$m$$$ and $$$k$$$ ($$$2 \le n \le 3 \cdot 10^5$$$, $$$1 \le m \le 3 \cdot 10^5$$$, $$$n - 1 \le m$$$, $$$0 \le k \le m$$$) — the number of vertices and edges in the graph, and the maximum number of edges that can be retained in the graph, respectively. Then $$$m$$$ lines follow, each containing three integers $$$x$$$, $$$y$$$, $$$w$$$ ($$$1 \le x, y \le n$$$, $$$x \ne y$$$, $$$1 \le w \le 10^9$$$), denoting an edge connecting vertices $$$x$$$ and $$$y$$$ and having weight $$$w$$$. The given graph is connected (any vertex can be reached from any other vertex) and simple (there are no self-loops, and for each unordered pair of vertices there exists at most one edge connecting these vertices).

In the first line print $$$e$$$ — the number of edges that should remain in the graph ($$$0 \le e \le k$$$). In the second line print $$$e$$$ distinct integers from $$$1$$$ to $$$m$$$ — the indices of edges that should remain in the graph. Edges are numbered in the same order they are given in the input. The number of good vertices should be as large as possible.

import core.bitop, std.bitmanip;
import core.checkedint;
import std.algorithm, std.functional;
import std.array, std.container;
import std.bigint;
import std.conv;
import std.datetime.stopwatch;
import std.math, std.numeric;
import std.range, std.range.interfaces;
import std.stdio, std.string;
import std.typecons;

struct edge {
    int u, v, w, id;
}

void main()
{
    int n, m, k;
    readf("%s %s %s", &n, &m, &k);
    readln;

    k = min(k, n-1);

    auto g = new edge[][] (n+1);
    foreach (i; 0 .. m) {
        edge e;
        readf("%s %s %s", &e.u, &e.v, &e.w);
        readln;

        e.id = i+1;
        g[e.u] ~= e;
        g[e.v] ~= e;
    }

    debug { g.writeln; }

    auto q = make!(RedBlackTree!(Tuple!(long, int, int)));
    q.insert(tuple(0L, 1, -1));
    auto isIn = new bool[] (n+1);
    isIn[] = false;

    int[] ans;
    while (ans.length < k) {
        auto t = q.front();
        q.removeFront();

        auto w = t[0];
        auto x = t[1];
        auto eid = t[2];

        if (isIn[x]) { continue; }

        isIn[x] = true;
        if (eid != -1) { ans ~= eid; }

        foreach (adjedge; g[x]) {
            int adj = adjedge.u != x ? adjedge.u : adjedge.v;
            if (isIn[adj]) { continue; }

            q.insert(tuple(w + adjedge.w, adj, adjedge.id));
        }
    }

    ans.length.writeln;
    ans.writefln!"%(%s %)";
}

import core.bitop, std.bitmanip;
import core.checkedint;
import std.algorithm, std.functional;
import std.array, std.container;
import std.bigint;
import std.conv;
import std.datetime.stopwatch;
import std.math, std.numeric;
import std.range, std.range.interfaces;
import std.stdio, std.string;
import std.typecons;

struct edge {
    int u, v, w, id;

    bool opEquals(const edge other) { return this.id == other.id; }
    int opCmp(ref const edge other) const { return this.w < other.w ? -1 : (this.w > other.w ? 1 : 0); }
}

void main()
{
    int n, m, k;
    readf("%s %s %s", &n, &m, &k);
    readln;

    k = min(k, n-1);

    auto g = new edge[][] (n+1);
    foreach (i; 0 .. m) {
        edge e;
        readf("%s %s %s", &e.u, &e.v, &e.w);
        readln;

        e.id = i+1;
        g[e.u] ~= e;
        g[e.v] ~= e;
    }

    debug { g.writeln; }

    auto q = make!(RedBlackTree!(Tuple!(long, int, int)));
    q.insert(tuple(0L, 1, -1));
    auto isIn = new bool[] (n+1);

    int[] ans;
    foreach (i; 0 .. k+1) {
        auto t = q.front();
        q.removeFront();

        auto w = t[0];
        auto x = t[1];
        auto eid = t[2];

        if (isIn[x]) { continue; }

        isIn[x] = true;
        if (eid != -1) { ans ~= eid; }

        foreach (adjedge; g[x]) {
            int adj = adjedge.u != x ? adjedge.u : adjedge.v;
            if (isIn[adj]) { continue; }

            q.insert(tuple(w + adjedge.w, adj, adjedge.id));
        }
    }

    ans.length.writeln;
    ans.writefln!"%(%s %)";
}

import core.bitop, std.bitmanip;
import core.checkedint;
import std.algorithm, std.functional;
import std.array, std.container;
import std.bigint;
import std.conv;
import std.datetime.stopwatch;
import std.math, std.numeric;
import std.range, std.range.interfaces;
import std.stdio, std.string;
import std.typecons;

struct edge {
    int u, v, w, id;

    bool opEquals(const edge other) { return this.id == other.id; }
    int opCmp(ref const edge other) const { return this.w < other.w ? -1 : (this.w > other.w ? 1 : 0); }
}

void main()
{
    int n, m, k;
    readf("%s %s %s", &n, &m, &k);
    readln;

    k = min(k, n-1);

    auto g = new edge[][] (n+1);
    foreach (i; 0 .. m) {
        edge e;
        readf("%s %s %s", &e.u, &e.v, &e.w);
        readln;

        e.id = i+1;
        g[e.u] ~= e;
        g[e.v] ~= e;
    }

    debug { g.writeln; }

    auto isIn = new bool[] (n+1);
    isIn[1] = true;
    auto toConsider = make!(RedBlackTree!edge)(g[1]);
    debug { toConsider.writeln; }

    int[] ans;
    foreach (i; 0 .. k) {
        auto found = false;
        edge curedge;
        do {
            curedge = toConsider.front;
            toConsider.removeFront();
            if (isIn[curedge.u] && isIn[curedge.v]) { continue; }

            found = true;
        } while (!found);

        debug { curedge.writeln; }

        ans ~= curedge.id;

        auto nxt = isIn[curedge.u] ? curedge.v : curedge.u;
        foreach (adjedge; g[nxt]) {
            int adj = adjedge.u != nxt ? adjedge.u : adjedge.v;
            if (isIn[adj]) { continue; }

            toConsider.insert(adjedge);
        }
    }

    ans.length.writeln;
    ans.writefln!"%(%s %)";
}

import core.bitop, std.bitmanip;
import core.checkedint;
import std.algorithm, std.functional;
import std.array, std.container;
import std.bigint;
import std.conv;
import std.datetime.stopwatch;
import std.math, std.numeric;
import std.range, std.range.interfaces;
import std.stdio, std.string;
import std.typecons;

struct edge {
    int u, v, w, id;
}

void main()
{
    int n, m, k;
    readf("%s %s %s", &n, &m, &k);
    readln;

    k = min(k, n-1);

    auto g = new edge[][] (n+1);
    foreach (i; 0 .. m) {
        edge e;
        readf("%s %s %s", &e.u, &e.v, &e.w);
        readln;

        e.id = i+1;
        g[e.u] ~= e;
        g[e.v] ~= e;
    }

    debug { g.writeln; }

    auto q = make!(RedBlackTree!(Tuple!(long, int, int)));
    q.insert(tuple(0L, 1, -1));
    auto isIn = new bool[] (n+1);
    isIn[] = false;

    int[] ans;
    foreach (i; 0 .. k+1) {
        auto t = q.front();
        q.removeFront();

        auto w = t[0];
        auto x = t[1];
        auto eid = t[2];

        if (isIn[x]) { continue; }

        isIn[x] = true;
        if (eid != -1) { ans ~= eid; }

        foreach (adjedge; g[x]) {
            int adj = adjedge.u != x ? adjedge.u : adjedge.v;
            if (isIn[adj]) { continue; }

            q.insert(tuple(w + adjedge.w, adj, adjedge.id));
        }
    }

    ans.length.writeln;
    ans.writefln!"%(%s %)";
}