#pragma GCC optimize("O3,unroll-loops")
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>

using namespace std;

// ================= 大數類別 (Base 2^32) =================
struct BigInt {
    vector<uint32_t> d;

    BigInt() {}
    BigInt(unsigned long long v) {
        while (v > 0) {
            d.push_back(v & 0xFFFFFFFF);
            v >>= 32;
        }
    }

    bool is_zero() const { return d.empty(); }
    
    void trim() {
        while (!d.empty() && d.back() == 0) d.pop_back();
    }

    bool is_even() const { return d.empty() || (d[0] & 1) == 0; }
    bool is_odd() const { return !d.empty() && (d[0] & 1) != 0; }

    int bits() const {
        if (d.empty()) return 0;
        int res = (d.size() - 1) * 32;
        uint32_t top = d.back();
        while (top) { res++; top >>= 1; }
        return res;
    }

    bool get_bit(int i) const {
        int word = i / 32;
        int bit = i % 32;
        if (word >= d.size()) return false;
        return (d[word] >> bit) & 1;
    }

    void set_bit(int i, bool val) {
        int word = i / 32;
        int bit = i % 32;
        while (d.size() <= word) d.push_back(0);
        if (val) d[word] |= (1u << bit);
        else d[word] &= ~(1u << bit);
        trim();
    }

    bool operator==(const BigInt& o) const { return d == o.d; }
    bool operator!=(const BigInt& o) const { return d != o.d; }
    bool operator<(const BigInt& o) const {
        if (d.size() != o.d.size()) return d.size() < o.d.size();
        for (int i = (int)d.size() - 1; i >= 0; --i) {
            if (d[i] != o.d[i]) return d[i] < o.d[i];
        }
        return false;
    }
    bool operator<=(const BigInt& o) const { return !(o < *this); }
    bool operator>(const BigInt& o) const { return o < *this; }
    bool operator>=(const BigInt& o) const { return !(*this < o); }

    BigInt operator+(const BigInt& o) const {
        BigInt res;
        uint64_t carry = 0;
        int n = max(d.size(), o.d.size());
        for (int i = 0; i < n || carry; ++i) {
            uint64_t sum = carry;
            if (i < d.size()) sum += d[i];
            if (i < o.d.size()) sum += o.d[i];
            res.d.push_back(sum & 0xFFFFFFFF);
            carry = sum >> 32;
        }
        res.trim();
        return res;
    }

    BigInt operator-(const BigInt& o) const {
        BigInt res;
        int64_t borrow = 0;
        for (int i = 0; i < d.size(); ++i) {
            int64_t diff = d[i] - borrow;
            if (i < o.d.size()) diff -= o.d[i];
            if (diff < 0) {
                diff += 0x100000000LL;
                borrow = 1;
            } else {
                borrow = 0;
            }
            res.d.push_back(diff);
        }
        res.trim();
        return res;
    }

    void shift_left_1() {
        if (d.empty()) return;
        uint32_t carry = 0;
        for (int i = 0; i < d.size(); ++i) {
            uint32_t next_carry = d[i] >> 31;
            d[i] = (d[i] << 1) | carry;
            carry = next_carry;
        }
        if (carry) d.push_back(carry);
    }

    void shift_right_1() {
        if (d.empty()) return;
        uint32_t carry = 0;
        for (int i = (int)d.size() - 1; i >= 0; --i) {
            uint32_t next_carry = (d[i] & 1) << 31;
            d[i] = (d[i] >> 1) | carry;
            carry = next_carry;
        }
        trim();
    }

    BigInt operator*(const BigInt& o) const {
        if (is_zero() || o.is_zero()) return BigInt();
        BigInt res;
        res.d.assign(d.size() + o.d.size(), 0);
        for (size_t i = 0; i < d.size(); ++i) {
            uint64_t carry = 0;
            for (size_t j = 0; j < o.d.size() || carry; ++j) {
                uint64_t cur = res.d[i+j] + d[i] * 1ULL * (j < o.d.size() ? o.d[j] : 0) + carry;
                res.d[i+j] = cur & 0xFFFFFFFF;
                carry = cur >> 32;
            }
        }
        res.trim();
        return res;
    }

    // 二進位長除法 (僅用於 Barrett 預處理)
    friend void divmod(const BigInt& a, const BigInt& b, BigInt& q, BigInt& r) {
        q.d.clear(); r.d.clear();
        if (a < b) { r = a; return; }
        for (int i = a.bits() - 1; i >= 0; --i) {
            r.shift_left_1();
            if (a.get_bit(i)) {
                if (r.d.empty()) r.d.push_back(1);
                else r.d[0] |= 1;
            }
            if (r >= b) {
                r = r - b;
                q.set_bit(i, true);
            }
        }
    }

    long long mod_small(long long b) const {
        long long rem = 0;
        long long base = (1ULL << 32) % b;
        for (int i = (int)d.size() - 1; i >= 0; --i) {
            rem = (rem * base + d[i]) % b;
        }
        return rem;
    }
};

// ================= Barrett Reduction =================
struct Barrett {
    BigInt N, mu;
    int k;

    Barrett(BigInt n) : N(n) {
        k = N.d.size();
        BigInt b2k;
        b2k.set_bit(2 * k * 32, true);
        BigInt rem;
        divmod(b2k, N, mu, rem);
    }

    BigInt reduce(BigInt A) const {
        BigInt q1;
        if (A.d.size() > k - 1) q1.d.assign(A.d.begin() + k - 1, A.d.end());
        BigInt q2 = q1 * mu;
        BigInt q3;
        if (q2.d.size() > k + 1) q3.d.assign(q2.d.begin() + k + 1, q2.d.end());

        BigInt r1;
        int r1_size = min((int)A.d.size(), k + 1);
        r1.d.assign(A.d.begin(), A.d.begin() + r1_size);
        r1.trim();

        BigInt r2 = q3 * N;
        int r2_size = min((int)r2.d.size(), k + 1);
        r2.d.resize(r2_size);
        r2.trim();

        BigInt r;
        if (r1 >= r2) r = r1 - r2;
        else {
            BigInt bk1;
            bk1.set_bit((k + 1) * 32, true);
            r = (r1 + bk1) - r2;
        }
        while (r >= N) r = r - N;
        return r;
    }

    BigInt mul(const BigInt& a, const BigInt& b) const {
        return reduce(a * b);
    }

    BigInt power(BigInt base, BigInt exp) const {
        BigInt res = 1;
        base = reduce(base);
        for (int i = 0; i < exp.bits(); ++i) {
            if (exp.get_bit(i)) res = mul(res, base);
            base = mul(base, base);
        }
        return res;
    }
};

// ================= BPSW 演算法 =================
BigInt parse(const string& s) {
    BigInt res;
    int i = 0;
    while (i < s.length()) {
        int len = min((int)s.length() - i, 9);
        long long val = stoll(s.substr(i, len));
        long long multiplier = 1;
        for(int j = 0; j < len; ++j) multiplier *= 10;
        res = res * BigInt(multiplier) + BigInt(val);
        i += len;
    }
    return res;
}

int jacobi(long long a, const BigInt& n) {
    int t = 1;
    long long n8 = n.mod_small(8);
    if (a < 0) {
        a = -a;
        if (n8 % 4 == 3) t = -t;
    }
    long long n_val = n.mod_small(a);
    while (a != 0) {
        while (a % 2 == 0) {
            a /= 2;
            if (n8 == 3 || n8 == 5) t = -t;
        }
        swap(a, n_val);
        if (a % 4 == 3 && n_val % 4 == 3) t = -t;
        a %= n_val;
    }
    if (n_val == 1) return t;
    return 0;
}

bool is_prime(BigInt n) {
    if (n == BigInt(2)) return true;
    if (n < BigInt(2) || n.is_even()) return false;

    // 1. 小質數試除 (加速過濾)
    static const int primes[] = {3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97};
    for (int p : primes) {
        if (n == BigInt(p)) return true;
        if (n.mod_small(p) == 0) return false;
    }

    Barrett barrett(n);

    // 2. Miller-Rabin (Base 2)
    BigInt d = n - BigInt(1);
    int s = 0;
    while (d.is_even()) {
        d.shift_right_1();
        s++;
    }
    
    BigInt x = barrett.power(BigInt(2), d);
    bool mr_pass = false;
    if (x == BigInt(1) || x == n - BigInt(1)) {
        mr_pass = true;
    } else {
        for (int i = 1; i < s; i++) {
            x = barrett.mul(x, x);
            if (x == n - BigInt(1)) {
                mr_pass = true;
                break;
            }
        }
    }
    if (!mr_pass) return false;

    // 3. 尋找 Lucas 參數 D (Selfridge 方法)
    long long D = 5;
    int sign = 1;
    while (true) {
        long long curD = D * sign;
        int j = jacobi(curD, n);
        if (j == -1) {
            D = curD;
            break;
        }
        if (j == 0) return false;
        D += 2;
        sign = -sign;
    }

    // 4. Strong Lucas Test
    long long Q = (1 - D) / 4;
    BigInt Q_mod = (Q < 0) ? n - BigInt(-Q) : BigInt(Q);
    BigInt D_mod = (D < 0) ? n - BigInt(-D) : BigInt(D);

    BigInt U = BigInt(1), V = BigInt(1);
    BigInt Qk = Q_mod;

    auto div2_mod = [&](BigInt A) {
        if (A.is_odd()) A = A + n;
        A.shift_right_1();
        if (A >= n) A = A - n;
        return A;
    };

    BigInt K = n + BigInt(1);
    BigInt d_lucas = K;
    int s_lucas = 0;
    while (d_lucas.is_even()) {
        d_lucas.shift_right_1();
        s_lucas++;
    }

    for (int i = d_lucas.bits() - 2; i >= 0; --i) {
        BigInt U_new = barrett.mul(U, V);
        BigInt V_new = barrett.mul(V, V) - barrett.mul(BigInt(2), Qk);
        if (V_new >= n) V_new = V_new + n; // 處理負數
        Qk = barrett.mul(Qk, Qk);

        U = U_new;
        V = V_new;

        if (d_lucas.get_bit(i)) {
            BigInt DU = barrett.mul(D_mod, U);
            U = div2_mod(U + V);
            V = div2_mod(DU + V);
            Qk = barrett.mul(Qk, Q_mod);
        }
    }

    if (U.is_zero() || V.is_zero()) return true;

    for (int r = 1; r < s_lucas; ++r) {
        V = barrett.mul(V, V) - barrett.mul(BigInt(2), Qk);
        if (V >= n) V = V + n;
        Qk = barrett.mul(Qk, Qk);
        if (V.is_zero()) return true;
    }

    return false;
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    string s;
    while (cin >> s) {
        if (is_prime(parse(s))) {
            cout << "YES\n";
        } else {
            cout << "NO\n";
        }
    }
    return 0;
}