#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); } |