#include <bits/stdc++.h>
using namespace std;

vector<pair<int, int>> get_factors(int x, int M, int N, unordered_map<int, vector<pair<int, int>>>& factor_cache) {
    if (factor_cache.find(x) != factor_cache.end()) {
        return factor_cache[x];
    }

    vector<pair<int, int>> factors;
    for (int a = 1; a * a <= x; ++a) {
        if (x % a == 0) {
            int b = x / a;
            if (a <= M && b <= N) factors.push_back({a, b});
            if (b <= M && a <= N && a != b) factors.push_back({b, a});
        }
    }

    factor_cache[x] = factors; 
    return factors;
}

int main() {
    int M, N;
    cin >> M >> N;
    

    vector<vector<int>> grid(M + 1, vector<int>(N + 1));
    for (int i = 1; i <= M; ++i) {
        for (int j = 1; j <= N; ++j) {
            cin >> grid[i][j];
        }
    }


    queue<pair<int, int>> q;
    q.push({1, 1});
    

    vector<vector<bool>> visited(M + 1, vector<bool>(N + 1, false));
    visited[1][1] = true;

    unordered_map<int, vector<pair<int, int>>> factor_cache;

    while (!q.empty()) {
        auto [r, c] = q.front();
        q.pop();

        if (r == M && c == N) {
            cout << "yes" << endl;
            return 0;
        }


        int value = grid[r][c];
        vector<pair<int, int>> jumps = get_factors(value, M, N, factor_cache);


        for (auto [a, b] : jumps) {
            if (!visited[a][b]) {
                visited[a][b] = true;
                q.push({a, b});
            }
        }
    }
    
    cout << "no" << endl;
    return 0;
}