#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