#include <cstdio>
#include <cassert>
#define REP(a, n) for (int a = 0; a < (n); ++a)
#define FOR(a, b, c) for (int a = (b); a <= (c); ++a)
typedef long long LL;
using namespace std;
//////////////////////
#define MOD 1'000'000'007
void gcdExtended(LL a, LL b, LL &x, LL &y) {
    if (a == 0) {
        x = 0, y = 1;
    }
    else {
        LL y1;
        gcdExtended(b % a, a, y, y1);
        x = y1 - (b / a) * y;
    }
}
LL inv(int A)
{
    LL x, y;
    gcdExtended(A, MOD, x, y);
    return (x % MOD + MOD) % MOD;
}
 
LL licz = 0, mian = 1, poz, neg;
inline void dodaj(LL l2, LL m2) {
//    printf("dodaj %d/%d\n", (int)l2, (int)m2);
    licz = (licz * m2 + l2 * mian) % MOD;
    mian = (mian * m2) % MOD;
}
int N,P;
int perm[3000][3000], byl[3000][3000], cur = 1;
void go(int a, int b) {
    if (byl[a][b]==cur) return;
    if (byl[a][b]) throw 0;
    byl[a][b] = cur;
    byl[b][a] = cur+1;
    if (a<b) poz++; else neg++;
    REP(p, P)
        go(perm[p][a], perm[p][b]);
}
int main() {
    scanf("%d%d", &N, &P);
    REP(a, P)
        REP(b, N) {
            scanf("%d", &perm[a][b]);
            --perm[a][b];
        }
    REP(b, N)
        REP(a, b)
            if (!byl[a][b]) {
                try {
                    cur += 2;
                    poz = neg = 0;
                    go(a, b);
                    dodaj(2*poz*neg%MOD, poz+neg);
                }
                catch(...){
                    dodaj(poz+neg, 2);
                }
            }
    int res = licz*inv(mian)%MOD;
    printf("%d\n", res);
}
        1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76  | #include <cstdio> #include <cassert> #define REP(a, n) for (int a = 0; a < (n); ++a) #define FOR(a, b, c) for (int a = (b); a <= (c); ++a) typedef long long LL; using namespace std; ////////////////////// #define MOD 1'000'000'007 void gcdExtended(LL a, LL b, LL &x, LL &y) { if (a == 0) { x = 0, y = 1; } else { LL y1; gcdExtended(b % a, a, y, y1); x = y1 - (b / a) * y; } } LL inv(int A) { LL x, y; gcdExtended(A, MOD, x, y); return (x % MOD + MOD) % MOD; } LL licz = 0, mian = 1, poz, neg; inline void dodaj(LL l2, LL m2) { // printf("dodaj %d/%d\n", (int)l2, (int)m2); licz = (licz * m2 + l2 * mian) % MOD; mian = (mian * m2) % MOD; } int N,P; int perm[3000][3000], byl[3000][3000], cur = 1; void go(int a, int b) { if (byl[a][b]==cur) return; if (byl[a][b]) throw 0; byl[a][b] = cur; byl[b][a] = cur+1; if (a<b) poz++; else neg++; REP(p, P) go(perm[p][a], perm[p][b]); } int main() { scanf("%d%d", &N, &P); REP(a, P) REP(b, N) { scanf("%d", &perm[a][b]); --perm[a][b]; } REP(b, N) REP(a, b) if (!byl[a][b]) { try { cur += 2; poz = neg = 0; go(a, b); dodaj(2*poz*neg%MOD, poz+neg); } catch(...){ dodaj(poz+neg, 2); } } int res = licz*inv(mian)%MOD; printf("%d\n", res); }  | 
            
        
                    English