@file:Suppress("NOTHING_TO_INLINE", "EXPERIMENTAL_FEATURE_WARNING", "OVERRIDE_BY_INLINE")
@file:OptIn(ExperimentalStdlibApi::class)

import java.io.PrintWriter
import java.util.Arrays
import java.util.NoSuchElementException
import java.util.TreeSet
import kotlin.math.*
import kotlin.random.Random
import kotlin.collections.sort as _sort
import kotlin.collections.sortDescending as _sortDescending
import kotlin.io.println as iprintln

/** @author Spheniscine */
fun main() { _writer.solve(); _writer.flush() }
fun PrintWriter.solve() {
//    val startTime = System.nanoTime()

    val numCases = 1//readInt()
    case@ for(case in 1..numCases) {
//        print("Case #$case: ")

        object {
            val n = readInt()
            val m = readInt()
            val q = readInt()

            val P = readIntArray(n)

            val A = IntArray(m)
            val B = IntArray(m) {
                A[it] = readInt() - 1
                readInt() - 1
            }

            val T = IntArray(q)
            val X = IntArray(q) {
                T[it] = readInt()
                readInt() - 1
            }

            val boss = IntList()
            val dsu = IntList(n) { it }
            val empty = IntList(0)
            val G = MutableList(n) { empty }

            fun addVertex(): Int {
                G.add(IntList(2))
                dsu.add(dsu.size)
                return dsu.lastIndex
            }

            tailrec fun root(v: Int): Int = if(dsu[v] == v) v else {
                dsu[v] = dsu[dsu[v]]
                root(dsu[v])
            }

            fun merge(u: Int, v: Int) {
                val ru = root(u)
                val rv = root(v)

                if(ru == rv) return

                val b = addVertex()
                dsu[ru] = b
                dsu[rv] = b
                G[b].add(ru)
                G[b].add(rv)
            }

            init {
                val E = BooleanArray(m)
                for(i in 0 until q) if(T[i] == 2) E[X[i]] = true
                for(i in 0 until m) if(!E[i]) {
                    merge(A[i], B[i])
                }

                for(i in q-1 downTo 0) {
                    val x = X[i]
                    when(T[i]) {
                        1 -> boss.add(root(x))
                        2 -> merge(A[x], B[x])
                    }
                }
                boss.reverse()

                val start = IntArray(dsu.size) { -1 }
                val end = IntArray(dsu.size)
                val stk = IntList()
                var eul = 0
                for(i in dsu.indices) if(start[i] == -1) {
                    val r = root(i)
                    stk.add(r)

                    while(stk.isNotEmpty()) {
                        val u = stk.pop()
                        if(start[u] == -1) {
                            start[u] = eul
                            if(u < n) eul++
                            stk.add(u)
                            for(v in G[u]) stk.add(v)
                        } else {
                            end[u] = eul
                        }
                    }
                }

                val S = SegmentTree(eul)

                for(i in 0 until n) {
                    val j = start[i]
                    S.delayedSet(j, IntPair(P[i], j))
                }

                S.pushDelayed()

                for(b in boss) {
                    val (x, j) = S[start[b], end[b]]
                    println(x)
                    S[j] = IntPair(0, j)
                }
            }

        }
    }

//    iprintln("Time: ${(System.nanoTime() - startTime) / 1000000} ms")
}

class SegmentTree(
    val size: Int) {

    val identityValue: IntPair = IntPair(-1, -1)
    inline fun combiner(a: IntPair, b: IntPair): IntPair = if(a.x >= b.x) a else b

    @Suppress("UNCHECKED_CAST")
    val array = IntPairArray(size shl 1) { identityValue }

    inline val lastIndex get() = size - 1
    inline val indices get() = 0 until size
    val asList: List<IntPair> by lazy {
        object : AbstractList<IntPair>() {
            override val size: Int get() = this@SegmentTree.size
            override fun get(index: Int): IntPair = this@SegmentTree[index]
        }
    }

    inline fun build(generator: (Int) -> IntPair) {
        for(i in 0 until size) {
            array[i + size] = generator(i)
        }
        for(i in size-1 downTo 1) {
            array[i] = combiner(array[i shl 1], array[i shl 1 or 1])
        }
    }

    /** alternative to build for arbitrary order **/
    fun delayedSet(i: Int, v: IntPair) { array[i + size] = v }
    fun pushDelayed() {
        for(i in size-1 downTo 1) {
            array[i] = combiner(array[i shl 1], array[i shl 1 or 1])
        }
    }

    /** instantiates values from an iterable, O(n) time */
    fun copyFrom(iterable: Iterable<IntPair>) {
        run {
            iterable.forEachIndexed { i, t ->
                if(i > lastIndex) return@run
                array[i + size] = t
            }
        }
        for(i in size-1 downTo 1) {
            array[i] = combiner(array[i shl 1], array[i shl 1 or 1])
        }
    }

    /** Updates a value, O(log n) time */
    operator fun set(index: Int, value: IntPair) {
        require(index in 0 until size)
        var i = index + size
        array[i] = value
        while(true) {
            i = i shr 1
            if(i <= 0) break
            array[i] = combiner(array[i shl 1], array[i shl 1 or 1])
        }
    }

    /** Gets a value by its index, O(1) time */
    operator fun get(index: Int): IntPair {
        require(index in 0 until size)
        return array[index + size]
    }

    /** gets the result of applying the monoid operation to the values in the index range, O(log n) time */
    operator fun get(start: Int, endExclusive: Int): IntPair {
        var l = maxOf(start, 0) + size
        var r = minOf(endExclusive, size) + size

        // two accumulators to support non-commutative monoids
        var lAcc = identityValue
        var rAcc = identityValue

        while(l < r) {
            if(l and 1 == 1) {
                lAcc = combiner(lAcc, array[l++])
            }
            if(r and 1 == 1) {
                rAcc = combiner(array[--r], rAcc)
            }

            l = l shr 1
            r = r shr 1
        }

        return combiner(lAcc, rAcc)
    }

    operator fun get(range: IntRange) = get(range.first, range.last + 1)
}

fun Int.bitConcat(other: Int) = toLong().shl(32) or other.toLong().and(0xffff_ffff)

inline class IntPair(val data: Long) {
    val x get() = (data shr 32).toInt()
    val y get() = data.toInt()
    inline operator fun component1() = x
    inline operator fun component2() = y

    override fun toString() = "($x, $y)"
}
fun IntPair(x: Int, y: Int) = IntPair(x.bitConcat(y))
fun unorderedPair(x: Int, y: Int) = if(x < y) IntPair(x, y) else IntPair(y, x)

inline class IntPairArray(val longArray: LongArray): Collection<IntPair> {
    inline operator fun get(i: Int) = IntPair(longArray[i])
    inline operator fun set(i: Int, v: IntPair) { longArray[i] = v.data }

    override inline val size: Int get() = longArray.size
    inline val lastIndex get() = longArray.lastIndex
    inline val indices get() = longArray.indices

    override inline fun contains(element: IntPair): Boolean = element.data in longArray

    override fun containsAll(elements: Collection<IntPair>): Boolean = elements.all(::contains)

    override inline fun isEmpty(): Boolean = longArray.isEmpty()

    override fun iterator(): Iterator<IntPair> = object: Iterator<IntPair> {
        var index = 0
        override fun hasNext(): Boolean = index < size
        override fun next(): IntPair = get(index++)
    }

    fun copyOf(newSize: Int) = IntPairArray(longArray.copyOf(newSize))
    fun copyOf() = copyOf(size)
}
fun IntPairArray.copyInto(destination: IntPairArray, destinationOffset: Int = 0, startIndex: Int = 0, endIndex: Int = size) =
    IntPairArray(longArray.copyInto(destination.longArray, destinationOffset, startIndex, endIndex))
inline fun IntPairArray(size: Int) = IntPairArray(LongArray(size))
inline fun IntPairArray(size: Int, init: (Int) -> IntPair) = IntPairArray(LongArray(size) { init(it).data })

inline fun IntPairArray.first() = get(0)
inline fun IntPairArray.last() = get(lastIndex)
inline fun <R> IntPairArray.fold(init: R, op: (acc: R, IntPair) -> R) = longArray.fold(init) { acc, i -> op(acc, IntPair(i)) }
inline fun <R> IntPairArray.foldRight(init: R, op: (IntPair, acc: R) -> R) = longArray.foldRight(init) { i, acc -> op(
    IntPair(i), acc) }

class IntList(initialCapacity: Int = 12) {
    private var _arr = IntArray(initialCapacity)
    private val capacity get() = _arr.size
    var size = 0
        private set
    inline val lastIndex get() = size - 1
    inline val indices get() = 0 until size

    constructor(copyFrom: IntArray): this(copyFrom.size) { copyFrom.copyInto(_arr); size = copyFrom.size }
    constructor(copyFrom: Collection<Int>): this(copyFrom.size) { _arr = copyFrom.toIntArray(); size = copyFrom.size }

    fun contentEquals(other: IntList): Boolean {
        return this === other || size == other.size && indices.all { this[it] == other[it] }
    }

    private fun grow(minCapacity: Int = 8) {
        val newCapacity = maxOf(minCapacity, capacity + (capacity shr 1))
        _arr = _arr.copyOf(newCapacity)
    }

    fun ensureCapacity(minCapacity: Int) { if(capacity < minCapacity) grow(minCapacity) }

    operator fun get(index: Int): Int {
        require(index in 0 until size)
        return _arr[index]
    }

    operator fun set(index: Int, value: Int) {
        require(index in 0 until size)
        _arr[index] = value
    }

    fun add(value: Int) {
        if(size == capacity) grow()
        _arr[size++] = value
    }

    fun addAll(list: IntList) {
        ensureCapacity(size + list.size)
        list._arr.copyInto(_arr, size, 0, list.size)
        size += list.size
    }

    fun add(index: Int, element: Int) {
        if(size == capacity) grow()
        _arr.copyInto(_arr, index + 1, index, size)
        size++
        set(index, element)
    }

    fun clear() { size = 0 }

    fun removeAt(index: Int): Int {
        val e = get(index)
        _arr.copyInto(_arr, index, index + 1, size)
        size--
        return e
    }

    fun indexOf(e: Int): Int {
        for(i in 0 until size) if(this[i] == e) return i
        return -1
    }

    fun remove(e: Int): Boolean {
        val i = indexOf(e)
        if(i == -1) return false
        removeAt(i)
        return true
    }

    operator fun iterator() = object: IntIterator() {
        private var pos = 0
        override fun hasNext() = pos < size
        override fun nextInt() = get(pos++)
    }

    inline fun isEmpty() = size == 0
    inline fun isNotEmpty() = size != 0

    fun pop() = _arr[--size]

    fun popToSize(s: Int) {
        require(s >= 0)
        if(s < size) size = s
    }

    fun swap(i: Int, j: Int) { val t = this[i]; this[i] = this[j]; this[j] = t }
    fun reverse() {
        for(i in 0 until size / 2) swap(i, lastIndex - i)
    }

    fun shuffle(rnd: Random = random) { for(i in lastIndex downTo 1) swap(i, rnd.nextInt(i + 1)) }
    fun sort() { shuffle(); _arr._sort(0, size) }
    fun sortDescending() { sort(); reverse() }

    fun joinToString(separator: CharSequence) = if(size == 0) "" else let {
        buildString {
            append(it[0])
            for (i in 1 until size) {
                append(separator).append(it[i])
            }
        }
    }

    override fun toString() = "[" + joinToString(", ") + "]"

    fun toIntArray() = _arr.copyOf(size)
    fun toList() = List(size, ::get)

    inline fun first() = get(0)
    inline fun last() = get(lastIndex)
}

inline fun IntList(size: Int, init: (Int) -> Int) = IntList(size).apply {
    for(i in 0 until size) { add(init(i)) }
}
inline fun IntArray.toIntList() = IntList(this)
inline fun Collection<Int>.toIntList() = IntList(this)
inline fun intListOf(vararg values: Int) = IntList(values)

fun IntList.max() = (1 until size).fold(this[0]) { acc, i -> max(acc, this[i]) }
fun IntList.min() = (1 until size).fold(this[0]) { acc, i -> min(acc, this[i]) }
fun IntList.getOrNull(i: Int) = if(i in indices) get(i) else null
inline fun IntList.count(predicate: (Int) -> Boolean) = indices.count { predicate(this[it]) }
fun IntList.copyOf() = IntList(size, ::get)

/** IO */
//const val PATH = "src/main/resources/"
//@JvmField val INPUT = File(PATH + "input.txt").inputStream()
//@JvmField val OUTPUT = File(PATH + "output.txt").outputStream()
@JvmField val INPUT = System.`in`
@JvmField val OUTPUT = System.out

const val _BUFFER_SIZE = 1 shl 16
@JvmField val _buffer = ByteArray(_BUFFER_SIZE)
@JvmField var _bufferPt = 0
@JvmField var _bytesRead = 0

tailrec fun readChar(): Char {
    if(_bufferPt == _bytesRead) {
        _bufferPt = 0
        _bytesRead = INPUT.read(_buffer, 0, _BUFFER_SIZE)
    }
    return if(_bytesRead < 0) Char.MIN_VALUE
    else {
        val c = _buffer[_bufferPt++].toChar()
        if (c == '\r') readChar()
        else c
    }
}

/** @param skipNext Whether to skip the next character (usually whitespace), defaults to true */
fun readCharArray(n: Int, skipNext: Boolean = true): CharArray {
    val res = CharArray(n) { readChar() }
    if(skipNext) readChar()
    return res
}

fun readLine(): String? {
    var c = readChar()
    return if(c == Char.MIN_VALUE) null
    else buildString {
        while(c != '\n' && c != Char.MIN_VALUE) {
            append(c)
            c = readChar()
        }
    }
}
fun readLn() = readLine()!!

fun read() = buildString {
    var c = readChar()
    while(c <= ' ') {
        if(c == Char.MIN_VALUE) return@buildString
        c = readChar()
    }
    do {
        append(c)
        c = readChar()
    } while(c > ' ')
}
fun readInt() = read().toInt()
fun readDouble() = read().toDouble()
fun readLong() = read().toLong()
fun readStrings(n: Int) = List(n) { read() }
fun readLines(n: Int) = List(n) { readLn() }
fun readInts(n: Int) = List(n) { read().toInt() }
fun readIntArray(n: Int) = IntArray(n) { read().toInt() }
fun readDoubles(n: Int) = List(n) { read().toDouble() }
fun readDoubleArray(n: Int) = DoubleArray(n) { read().toDouble() }
fun readLongs(n: Int) = List(n) { read().toLong() }
fun readLongArray(n: Int) = LongArray(n) { read().toLong() }

@JvmField val _writer = PrintWriter(OUTPUT, false)

/**  sort overrides to avoid quicksort attacks */

@JvmField var _random: Random? = null
val random get() = _random ?: Random(0x594E215C123 * System.nanoTime()).also { _random = it }

fun IntArray.sort() { shuffle(random); _sort() }
fun IntArray.sortDescending() { shuffle(random); _sortDescending() }

fun LongArray.sort() { shuffle(random); _sort() }
fun LongArray.sortDescending() { shuffle(random); _sortDescending() }

fun DoubleArray.sort() { shuffle(random); _sort() }
fun DoubleArray.sortDescending() { shuffle(random); _sortDescending() }

inline fun CharArray.sort() { _sort() }
inline fun CharArray.sortDescending() { _sortDescending() }

inline fun <T : Comparable<T>> Array<out T>.sort() = _sort()
inline fun <T : Comparable<T>> Array<out T>.sortDescending() = _sortDescending()
inline fun <T : Comparable<T>> MutableList<out T>.sort() = _sort()
inline fun <T : Comparable<T>> MutableList<out T>.sortDescending() = _sortDescending()

// import preserving junk function
@Suppress("NonAsciiCharacters") fun 雪花飄飄北風嘯嘯天地一片蒼茫() { iprintln(max(1, 2)) }

// max/min Kotlin 1.6 -> 1.4 shim
fun IntArray.max() = maxOf { it }
fun IntArray.min() = minOf { it }
fun LongArray.max() = maxOf { it }
fun LongArray.min() = minOf { it }
fun CharArray.max() = maxOf { it }
fun CharArray.min() = minOf { it }
fun <T : Comparable<T>> Iterable<T>.max() = maxOf { it }
fun <T : Comparable<T>> Iterable<T>.min() = minOf { it }
fun <T : Comparable<T>> Sequence<T>.max() = maxOf { it }
fun <T : Comparable<T>> Sequence<T>.min() = minOf { it }


import java.io.BufferedReader
import java.io.InputStream
import java.io.InputStreamReader
import java.util.*
import kotlin.math.abs
import kotlin.math.max
import kotlin.math.min

val MOD = 1_000_000_007

class Solver(stream: InputStream, private val out: java.io.PrintWriter) {
  fun solve() {
    val A = ni()
    val B = ni()
    if (B > A) {
      out.println(0)
      return
    }

    if (A == B) {
      out.println("infinity")
      return
    }

    val mx = (A - B)
    var x = 1
    var ans = 0
    while(x * x <= mx) {
      if (mx % x == 0) {
        if (A % x == B) ans++
        if (x * x != mx && A % (mx / x) == B) ans++
      }
      x++
    }
    out.println(ans)
  }

  private val isDebug = try {
    // なんか本番でエラーでる
    System.getenv("MY_DEBUG") != null
  } catch (t: Throwable) {
    false
  }

  private var tokenizer: StringTokenizer? = null
  private val reader = BufferedReader(InputStreamReader(stream), 32768)
  private fun next(): String {
    while (tokenizer == null || !tokenizer!!.hasMoreTokens()) {
      tokenizer = StringTokenizer(reader.readLine())
    }
    return tokenizer!!.nextToken()
  }

  private fun ni() = next().toInt()
  private fun nl() = next().toLong()
  private fun ns() = next()
  private fun na(n: Int, offset: Int = 0): IntArray {
    return map(n, offset) { ni() }
  }

  private inline fun map(n: Int, offset: Int = 0, f: (Int) -> Int): IntArray {
    val res = IntArray(n)
    for (i in 0 until n) {
      res[i] = f(i + offset)
    }
    return res
  }

  private inline fun debug(msg: () -> String) {
    if (isDebug) System.err.println(msg())
  }

  private fun debug(a: LongArray) {
    debug { a.joinToString(" ") }
  }

  private fun debug(a: IntArray) {
    debug { a.joinToString(" ") }
  }

  private fun debug(a: BooleanArray) {
    debug { a.map { if (it) 1 else 0 }.joinToString("") }
  }

  private fun debugDim(A: Array<IntArray>) {
    if (isDebug) {
      for (a in A) {
        debug(a)
      }
    }
  }

  /**
   * 勝手にimport消されるのを防ぎたい
   */
  private fun hoge() {
    min(1, 2)
    max(1, 2)
    abs(-10)
  }
}

fun <A, B> pair(a: A, b: B) = RPair(a, b)
data class RPair<A, B>(val _1: A, val _2: B)

fun main() {
  val out = java.io.PrintWriter(System.out)
  Solver(System.`in`, out).solve()
  out.flush()
}


@file:Suppress("NOTHING_TO_INLINE", "EXPERIMENTAL_FEATURE_WARNING", "OVERRIDE_BY_INLINE")
@file:OptIn(ExperimentalUnsignedTypes::class, ExperimentalStdlibApi::class)

import java.io.PrintWriter
import java.lang.StringBuilder
import kotlin.math.*
import kotlin.random.Random
import kotlin.system.exitProcess
import kotlin.collections.sort as _sort
import kotlin.collections.sortDescending as _sortDescending
import kotlin.io.println as iprintln

/** @author Spheniscine */
fun main() { _writer.solve(); _writer.flush() }
fun PrintWriter.solve() {
//    val startTime = System.nanoTime()

    val numCases = 1//readInt()

    case@ for(case in 1..numCases) {
    //    print("Case #$case: ")

        val n = readInt()
        val D = ModIntArray(n+1)
        for(i in 1..n) {
            var j = i
            while(j <= n) {
                D[j]++
                j += i
            }
        }

        var sum = ModInt(0)
        for(i in 1..n) {
            D[i] += sum
            sum += D[i]
        }

        val ans = D[n]
        println(ans.int)
    }

//    iprintln("Time: ${(System.nanoTime() - startTime) / 1000000} ms")
}

const val BILLION7 = 1e9.toInt() + 7
const val MOD = 998244353
const val TOTIENT = MOD - 1 // assumes MOD is prime

infix fun Int.modulo(mod: Int): Int = (this % mod).let { (it shr Int.SIZE_BITS - 1 and mod) + it }
infix fun Long.modulo(mod: Long) = (this % mod).let { (it shr Long.SIZE_BITS - 1 and mod) + it }
infix fun Long.modulo(mod: Int) = modulo(mod.toLong()).toInt()

fun Int.mulMod(other: Int, mod: Int) = toLong() * other modulo mod

fun Int.powMod(exponent: Long, mod: Int): Int {
    if(exponent < 0) error("Inverse not implemented")
    if(mod == 1) return 0
    var res = 1L
    var e = exponent
    var b = modulo(mod).toLong()

    while(e > 0) {
        if(e and 1 == 1L) {
            res = res * b % mod
        }
        e = e shr 1
        b = b * b % mod
    }
    return res.toInt()
}
fun Int.powMod(exponent: Int, mod: Int) = powMod(exponent.toLong(), mod)
fun Int.modPowArray(n: Int, mod: Int): IntArray {
    val res = IntArray(n+1)
    res[0] = 1
    for(i in 1..n) res[i] = mulMod(res[i-1], mod)
    return res
}

inline fun Int.toModInt() = ModInt(this modulo MOD)
inline fun Long.toModInt() = ModInt(this modulo MOD)

/** note: Only use constructor for int within modulo range, otherwise use toModInt **/
inline class ModInt(val int: Int) {
    companion object {
        /** can't seem to make these private or inlined without causing compiler issues */
        @JvmField val _invMemo = HashMap<ModInt, ModInt>()
        fun _invMemoized(m: ModInt) = _invMemo.getOrPut(m) { m.inv_unmemoized() }
    }

    // normalizes an integer that's within range [-MOD, MOD) without branching
    private inline fun normalize(int: Int) = ModInt((int shr Int.SIZE_BITS - 1 and MOD) + int)

    operator fun plus(other: ModInt) = normalize(int + other.int - MOD) // overflow-safe even if MOD >= 2^30
    inline operator fun plus(other: Int) = plus(other.toModInt())
    operator fun inc() = normalize(int + (1 - MOD))

    operator fun minus(other: ModInt) = normalize(int - other.int)
    inline operator fun minus(other: Int) = minus(other.toModInt())
    operator fun dec() = normalize(int - 1)
    operator fun unaryMinus() = normalize(-int)

    operator fun times(other: ModInt) = ModInt((int.toLong() * other.int % MOD).toInt())
    inline operator fun times(other: Int) = ModInt(int.mulMod(other, MOD))

    fun pow(exponent: Int): ModInt {
        val e = if(exponent < 0) {
            require(int != 0) { "Can't invert/divide by 0" }
            exponent modulo TOTIENT
        } else exponent
        return ModInt(int.powMod(e, MOD))
    }

    fun pow(exponent: Long) = if(int == 0) when {
        exponent > 0 -> this
        exponent == 0L -> ModInt(1)
        else -> error("Can't invert/divide by 0")
    } else pow(exponent modulo TOTIENT)

    inline fun inverse() = inv_unmemoized() /** NOTE: Change if necessary */

    fun inv_unmemoized(): ModInt {
        require(int != 0) { "Can't invert/divide by 0" }
        return pow(TOTIENT - 1)
    }
    inline fun inv_memoized() = _invMemoized(this)

    operator fun div(other: ModInt) = times(other.inverse())
    inline operator fun div(other: Int) = div(other.toModInt())

    override inline fun toString() = int.toString()
}

inline operator fun Int.plus(modInt: ModInt) = modInt + this
inline operator fun Int.minus(modInt: ModInt) = toModInt() - modInt
inline operator fun Int.times(modInt: ModInt) = modInt * this
inline operator fun Int.div(modInt: ModInt) = modInt.inverse() * this

inline class ModIntArray(val intArray: IntArray): Collection<ModInt> {
    inline operator fun get(i: Int) = ModInt(intArray[i])
    inline operator fun set(i: Int, v: ModInt) { intArray[i] = v.int }

    override inline val size: Int get() = intArray.size
    inline val lastIndex get() = intArray.lastIndex
    inline val indices get() = intArray.indices

    override inline fun contains(element: ModInt): Boolean = element.int in intArray

    override fun containsAll(elements: Collection<ModInt>): Boolean = elements.all(::contains)

    override inline fun isEmpty(): Boolean = intArray.isEmpty()

    override fun iterator(): Iterator<ModInt> = object: Iterator<ModInt> {
        var index = 0
        override fun hasNext(): Boolean = index < size
        override fun next(): ModInt = get(index++)
    }

    fun copyOf(newSize: Int) = ModIntArray(intArray.copyOf(newSize))
    fun copyOf() = copyOf(size)
}
fun ModIntArray.copyInto(destination: ModIntArray, destinationOffset: Int = 0, startIndex: Int = 0, endIndex: Int = size) =
    ModIntArray(intArray.copyInto(destination.intArray, destinationOffset, startIndex, endIndex))
inline fun ModIntArray(size: Int) = ModIntArray(IntArray(size))
inline fun ModIntArray(size: Int, init: (Int) -> ModInt) = ModIntArray(IntArray(size) { init(it).int })

fun ModInt.powArray(n: Int) = ModIntArray(int.modPowArray(n, MOD))

inline fun ModIntArray.first() = get(0)
inline fun ModIntArray.last() = get(lastIndex)
inline fun ModIntArray.joinToString(separator: CharSequence) = intArray.joinToString(separator)
inline fun <R> ModIntArray.fold(init: R, op: (acc: R, ModInt) -> R) = intArray.fold(init) { acc, i -> op(acc, ModInt(i)) }
inline fun <R> ModIntArray.foldRight(init: R, op: (ModInt, acc: R) -> R) = intArray.foldRight(init) { i, acc -> op(ModInt(i), acc) }
fun ModIntArray.sum() = fold(ModInt(0), ModInt::plus)
fun ModIntArray.product() = fold(ModInt(1), ModInt::times)

inline fun <T> Iterable<T>.sumByModInt(func: (T) -> ModInt) = fold(ModInt(0)) { acc, t -> acc + func(t) }
inline fun <T> Iterable<T>.productByModInt(func: (T) -> ModInt) = fold(ModInt(1)) { acc, t -> acc * func(t) }
inline fun <T> Sequence<T>.sumByModInt(func: (T) -> ModInt) = fold(ModInt(0)) { acc, t -> acc + func(t) }
inline fun <T> Sequence<T>.productByModInt(func: (T) -> ModInt) = fold(ModInt(1)) { acc, t -> acc * func(t) }
inline fun <T> Array<T>.sumByModInt(func: (T) -> ModInt) = fold(ModInt(0)) { acc, t -> acc + func(t) }
inline fun <T> Array<T>.productByModInt(func: (T) -> ModInt) = fold(ModInt(1)) { acc, t -> acc * func(t) }
fun Iterable<ModInt>.sum() = sumByModInt { it }
fun Sequence<ModInt>.sum() = sumByModInt { it }
fun Iterable<ModInt>.product() = productByModInt { it }
fun Sequence<ModInt>.product() = productByModInt { it }
fun Collection<ModInt>.toModIntArray() = ModIntArray(size).also { var i = 0; for(e in this) { it[i++] = e } }

/** IO */
//@JvmField val ONLINE_JUDGE = System.getProperty("ONLINE_JUDGE") != null
//const val PATH = "src/main/resources/"
//@JvmField val INPUT = File(PATH + "input.txt").inputStream()
//@JvmField val OUTPUT = File(PATH + "output.txt").outputStream()
@JvmField val INPUT = System.`in`
@JvmField val OUTPUT = System.out

const val _BUFFER_SIZE = 1 shl 16
@JvmField val _buffer = ByteArray(_BUFFER_SIZE)
@JvmField var _bufferPt = 0
@JvmField var _bytesRead = 0

tailrec fun readChar(): Char {
    if(_bufferPt == _bytesRead) {
        _bufferPt = 0
        _bytesRead = INPUT.read(_buffer, 0, _BUFFER_SIZE)
    }
    return if(_bytesRead < 0) Char.MIN_VALUE
    else {
        val c = _buffer[_bufferPt++].toChar()
        if (c == '\r') readChar() else c
    }
}

/** @param skipNext Whether to skip the next character (usually whitespace), defaults to true */
fun readCharArray(n: Int, skipNext: Boolean = true): CharArray {
    val res = CharArray(n) { readChar() }
    if(skipNext) readChar()
    return res
}

fun readLine(): String? {
    var c = readChar()
    return if(c == Char.MIN_VALUE) null
    else buildString {
        while(c != '\n' && c != Char.MIN_VALUE) {
            append(c)
            c = readChar()
        }
    }
}
fun readLn() = readLine()!!

fun read() = buildString {
    var c = readChar()
    while(c <= ' ') {
        if(c == Char.MIN_VALUE) return@buildString
        c = readChar()
    }
    do {
        append(c)
        c = readChar()
    } while(c > ' ')
}
fun readInt() = read().toInt()
fun readDouble() = read().toDouble()
fun readLong() = read().toLong()
fun readStrings(n: Int) = List(n) { read() }
fun readLines(n: Int) = List(n) { readLn() }
fun readInts(n: Int) = List(n) { read().toInt() }
fun readIntArray(n: Int) = IntArray(n) { read().toInt() }
fun readDoubles(n: Int) = List(n) { read().toDouble() }
fun readDoubleArray(n: Int) = DoubleArray(n) { read().toDouble() }
fun readLongs(n: Int) = List(n) { read().toLong() }
fun readLongArray(n: Int) = LongArray(n) { read().toLong() }

@JvmField val _writer = PrintWriter(OUTPUT, false)

/**  sort overrides to avoid quicksort attacks */

@JvmField var _random: Random? = null
val random get() = _random ?: Random(0x594E215C123 * System.nanoTime()).also { _random = it }

inline fun <A, T> _mergeSort(a0: A, n: Int, tmp0: A, get: A.(Int) -> T, set: A.(Int, T) -> Unit, cmp: (T, T) -> Int) {
    var a = a0
    var tmp = tmp0
    var len = 1
    while(len < n) {
        var l = 0
        while(true) {
            val m = l + len
            if(m >= n) break
            val r = min(n, m + len)
            var i = l
            var j = m
            for(k in l until r) {
                if(i != m && (j == r || cmp(a.get(i), a.get(j)) <= 0)) {
                    tmp.set(k, a.get(i++))
                } else tmp.set(k, a.get(j++))
            }
            l = r
        }
        for(i in l until n) tmp.set(i, a.get(i))
        val t = a; a = tmp; tmp = t
        len += len
    }
    if(a !== a0) for(i in 0 until n) a0.set(i, tmp0.get(i))
}

inline fun IntArray.sortWith(cmp: (Int, Int) -> Int) { _mergeSort(this, size, IntArray(size), IntArray::get, IntArray::set, cmp) }
inline fun <T: Comparable<T>> IntArray.sortBy(func: (Int) -> T) { sortWith { a, b -> func(a).compareTo(func(b)) } }
inline fun <T: Comparable<T>> IntArray.sortByDescending(func: (Int) -> T) { sortWith { a, b -> func(b).compareTo(func(a)) } }
fun IntArray.sort() { sortBy { it } }
fun IntArray.sortDescending() { sortByDescending { it } }

inline fun LongArray.sortWith(cmp: (Long, Long) -> Int) { _mergeSort(this, size, LongArray(size), LongArray::get, LongArray::set, cmp) }
inline fun <T: Comparable<T>> LongArray.sortBy(func: (Long) -> T) { sortWith { a, b -> func(a).compareTo(func(b)) } }
inline fun <T: Comparable<T>> LongArray.sortByDescending(func: (Long) -> T) { sortWith { a, b -> func(b).compareTo(func(a)) } }
fun LongArray.sort() { sortBy { it } }
fun LongArray.sortDescending() { sortByDescending { it } }

inline fun DoubleArray.sortWith(cmp: (Double, Double) -> Int) { _mergeSort(this, size, DoubleArray(size), DoubleArray::get, DoubleArray::set, cmp) }
inline fun <T: Comparable<T>> DoubleArray.sortBy(func: (Double) -> T) { sortWith { a, b -> func(a).compareTo(func(b)) } }
inline fun <T: Comparable<T>> DoubleArray.sortByDescending(func: (Double) -> T) { sortWith { a, b -> func(b).compareTo(func(a)) } }
fun DoubleArray.sort() { sortBy { it } }
fun DoubleArray.sortDescending() { sortByDescending { it } }

inline fun CharArray.sort() { _sort() }
inline fun CharArray.sortDescending() { _sortDescending() }

inline fun <T : Comparable<T>> Array<out T>.sort() = _sort()
inline fun <T : Comparable<T>> Array<out T>.sortDescending() = _sortDescending()
inline fun <T : Comparable<T>> MutableList<out T>.sort() = _sort()
inline fun <T : Comparable<T>> MutableList<out T>.sortDescending() = _sortDescending()

// import preserving junk function
@Suppress("NonAsciiCharacters") fun 雪花飄飄北風嘯嘯天地一片蒼茫() { iprintln(max(1, 2)) }

fun IntArray.sumLong() = sumOf { it.toLong() }

fun IntArray.sortedIndices() = IntArray(size) { it }.also { it.sortBy(::get) }
fun IntArray.sortedIndicesDescending() = IntArray(size) { it }.also { it.sortByDescending(::get) }
fun LongArray.sortedIndices() = IntArray(size) { it }.also { it.sortBy(::get) }
fun LongArray.sortedIndicesDescending() = IntArray(size) { it }.also { it.sortByDescending(::get) }
fun DoubleArray.sortedIndices() = IntArray(size) { it }.also { it.sortBy(::get) }
fun DoubleArray.sortedIndicesDescending() = IntArray(size) { it }.also { it.sortByDescending(::get) }
fun <T: Comparable<T>> Array<T>.sortedIndices() = IntArray(size) { it }.also { it.sortBy(::get) }
fun <T: Comparable<T>> Array<T>.sortedIndicesDescending() = IntArray(size) { it }.also { it.sortByDescending(::get) }
fun <T: Comparable<T>> List<T>.sortedIndices() = IntArray(size) { it }.also { it.sortBy(::get) }
fun <T: Comparable<T>> List<T>.sortedIndicesDescending() = IntArray(size) { it }.also { it.sortByDescending(::get) }

// max/min Kotlin 1.6 -> 1.4 shim
fun IntArray.max() = maxOf { it }
fun IntArray.min() = minOf { it }
fun LongArray.max() = maxOf { it }
fun LongArray.min() = minOf { it }
fun CharArray.max() = maxOf { it }
fun CharArray.min() = minOf { it }
fun <T : Comparable<T>> Iterable<T>.max() = maxOf { it }
fun <T : Comparable<T>> Iterable<T>.min() = minOf { it }
fun <T : Comparable<T>> Sequence<T>.max() = maxOf { it }
fun <T : Comparable<T>> Sequence<T>.min() = minOf { it }


import java.io.BufferedInputStream
import java.util.*

fun main(args: Array<String>) {
    val scanner = Scanner(BufferedInputStream(System.`in`))

    val n = scanner.nextInt()
    if(ok(n)) print("YES")
    else print("NO")

}

fun ok(x: Int): Boolean{
    var a = 1
    var i = 1
    while(a < x){
        if(isTri(x-a)) return true
        ++i
        a += i
    }
    return false
}

fun isTri(a: Int): Boolean{
    val base = (Math.sqrt(8.0 * a + 1) - 1)/2
    return (Math.ceil(base) == Math.floor(base))
}


import java.io.*
import java.util.*
import kotlin.math.max
import kotlin.math.min

fun main(args: Array<String>) {
    solve(System.`in`, System.out)
}

val MAX_N = (1e6 + 10).toInt()
val INF = (1e9 + 7).toInt()
val MOD = (1e9 + 7).toInt()
val INF_F = 1e-6

fun solve(input: InputStream, output: OutputStream) {
    val reader = InputReader(BufferedInputStream(input))
    val writer = PrintWriter(BufferedOutputStream(output))

    solve(reader, writer)
    writer.close()
}

fun solve(reader: InputReader, writer: PrintWriter) {
    val n = reader.nextInt()
    val a = reader.nextArrayInt(n)
    var l = 0
    while (l < n && a[l] == 0) {
        l++
    }
    if (l == n) {
        writer.println(n)
        return
    }

    var r = n - 1
    while (r >= l && a[r] == 1) {
        r--
    }

    if (r < l) {
        writer.println(n)
        return
    }

    val count0 = a.filterIndexed { index, value -> index in l..r && value == 0 }.count()
    var ans = n - min(r - l + 1 - count0, count0)
    for (i in 0 until n) {
        val x0 = a.filterIndexed { index, value -> index in 0..i && value == 0 }.count()
        val x1 = a.filterIndexed { index, value -> index in i+1 until n && value == 1 }.count()
        ans = max(ans, x0 + x1)
    }
    writer.println(ans)
}

/*

6
0 1 0 0 0 1

100
1 1 0 1 1 0 0 0 0 1 0 1 1 1 0 1 1 1 1 0 1 1 1 1 1 1 0 1 1 0 0 1 1 1 0 0 0 1 0 0 1 0 1 1 0 1 0 0 1 0 0 1 1 0 0 1 0 0 1 1 0 1 0 1 0 0 0 0 0 1 0 0 0 0 0 0 1 1 0 0 0 1 1 1 0 1 1 0 1 1 1 0 0 1 1 0 0 0 0 1

* */

fun gcd(a: Int, b: Int): Int {
    return if (b == 0) a else gcd(b, a % b)
}

class InputReader(stream: InputStream) {
    private val reader = BufferedReader(InputStreamReader(stream), 32768)
    private var tokenizer: StringTokenizer? = null

    operator fun next(): String {
        while (tokenizer == null || !tokenizer!!.hasMoreTokens()) {
            try {
                tokenizer = StringTokenizer(reader.readLine())
            } catch (e: IOException) {
                throw RuntimeException(e)
            }

        }
        return tokenizer!!.nextToken()
    }

    fun nextInt(): Int {
        return Integer.parseInt(next())
    }

    fun nextLong(): Long {
        return java.lang.Long.parseLong(next())
    }

    fun nextArrayInt(count: Int): IntArray {
        return nextArrayInt(0, count)
    }

    fun nextArrayInt(start: Int, count: Int): IntArray {
        val a = IntArray(start + count)
        for (i in start until start + count) {
            a[i] = nextInt()
        }
        return a
    }

    fun nextArrayLong(count: Int): LongArray {
        val a = LongArray(count)
        for (i in 0 until count) {
            a[i] = nextLong()
        }
        return a
    }
}


fun main() {
    readLine()
    print(readLine()!!.split(" ").mapIndexed { floor, habitants -> habitants.toInt() * 4 * floor }.sum())
}


import java.io.FileInputStream

val MOD : Long = 1000000007L
const val mod : Int = (1e9 + 7).toInt();

fun main(args: Array<String>) {
//    System.setIn(FileInputStream("./B/input3"));

    val (nRow, nCol, k) = readLine()!!.split(' ').map(String::toLong)

    if (k == -1L) {
        if ((nRow + nCol) % 2 == 1L) {
            println(0)
            return
        }
    }

    if (nRow < 2 || nCol < 2) {
        println(1)
        return
    }

    val dofRow = (nRow - 1)
    val dofCol = (nCol - 1)

    val x1 = qpow(2, dofCol)
    val x2 = qpow(x1, dofRow)
//    val x1 = powmod(2, dofCol)
//    val x2 = powmod(x1, dofRow)
    println(x2)
}

fun qpow(x: Long, exp: Long) : Long {
    var exp_ = exp % (MOD - 1)
    var res : Long = 1L
    var mult = x
    while (exp_ > 0) {
        if (exp_ % 2 == 1L) {
            res = (res * mult) % MOD
        }
        mult = (mult * mult) % MOD
        exp_ /= 2
    }
    return res % MOD
}

fun powmod(x: Long, y: Long) : Long {
    var ret = 1L;
    var y_ = y % (mod - 1)
    var x_ = x
    while( y_ > 0){
        if(1 == (y_ % 2).toInt()) {
            ret = (ret * x_) % mod
        }
        y_ /= 2
        x_ = (x_ * x_) % mod;
    }
    return ret;
}