#include <bits/stdc++.h> using namespace std; typedef long long ll; ll n,k; set<vector<ll> > aktperm; vector<ll> tab[3001]; vector<ll> zloz(vector<ll> A, vector<ll> B){ for (ll i = 0; i < n; i++){ A[i] = B[A[i]-1]; } return A; } const ll mod = 1e9+7; ll fastpot(ll a, ll b){ ll w = 1; while (b){ if (b%2) w = (w*a)%mod; a = (a*a)%mod; b /= 2; } return w%mod; } ll par[3001]; vector<ll> cykl[3001]; vector<pair<ll,ll> > pozycje[3001]; const ll base = (1<<12); ll tree[2*base]; void change(ll v, ll x){ v += base; while (v){ tree[v] = (tree[v]+x+mod)%mod; v /= 2; } } ll query(ll a, ll b){ a += base-1; b += base+1; ll wy = 0; while (b-a > 1){ if (!(a%2)) wy = (wy+tree[a+1]+mod)%mod; if (b%2) wy = (wy+tree[b-1]+mod)%mod; a /= 2; b /= 2; } return wy; } const ll base2 = (1<<4); ll tree2[2*base2]; void change2(ll v, ll x){ v += base2; while (v){ tree2[v] += x; v /= 2; } } ll query2(ll a, ll b){ a += base2-1; b += base2+1; ll wy = 0; while (b-a > 1){ if (!(a%2)) wy += tree2[a+1]; if (b%2) wy += tree2[b-1]; a /= 2; b /= 2; } return wy; } ll count_inversions(vector<ll> & permutacja){ ll wy = 0; for (ll x : permutacja){ wy += query2(x,base2-1); change2(x,1); } for (ll x : permutacja) change2(x,-1); return wy; } ll inv(ll x){ return fastpot(x,mod-2); } vector<ll> onwd[3001][3001]; ll gdzie[3001]; void solve2(){ ll i; ll tablica[n+1]; for (i = 1; i <= n; i++) cin>>tablica[i]; for (i = 1; i <= n; i++){ if (par[i]) continue; par[i] = i; cykl[i].push_back(i); ll x = tablica[i]; while (x != i){ par[x] = i; gdzie[x] = cykl[i].size(); cykl[i].push_back(x); x = tablica[x]; } } ll wy = 0; for (ll a = 1; a <= n; a++){ if (par[a] != a) continue; for (ll b = 1; b <= n; b++){ if (par[b] != b) continue; ll nwd = __gcd(cykl[a].size(),cykl[b].size()); for (i = 0; i < nwd; i++) onwd[b][i].clear(); for (ll i = 0; i < (ll)cykl[b].size(); i++){ ll x = cykl[b][i]; onwd[b][i%nwd].push_back(x); //cout<<"Dodajemy "<<x<<" na "<<b<<" "<<i%nwd<<"\n"; } } ll aktwy = 0; for (ll przes = 0; przes < (ll)cykl[a].size(); przes++){ for (i = 0; i < 2*base; i++) tree[i] = 0; for (i = 1; i <= n; i++){ if (par[i] == a){ ll x = cykl[a][(gdzie[i]+przes)%(cykl[a].size())]; aktwy = (aktwy+query(x,base-1))%mod; } ll nwd = __gcd(cykl[a].size(),cykl[par[i]].size()); for (ll x : onwd[par[i]][(gdzie[i]+przes)%nwd]){ //cout<<x<<" "<<inv(onwd[par[i]][(gdzie[i]+przes)%nwd].size())<<"\n"; change(x,inv(onwd[par[i]][(gdzie[i]+przes)%nwd].size())); } } } aktwy = (aktwy*inv(cykl[a].size()))%mod; wy = (wy+aktwy)%mod; } cout<<wy<<"\n"; } signed main(){ ios_base::sync_with_stdio(0); cin.tie(0); ll i; cin>>n>>k; if (k == 1){ solve2(); return 0; } queue<vector<ll> > Q; for (ll j = 0; j < k; j++){ tab[j].resize(n); for (i = 0; i < n; i++) cin>>tab[j][i]; aktperm.insert(tab[j]); Q.push(tab[j]); } while (Q.size()){ vector<ll> perm = Q.front(); Q.pop(); for (ll i = 0; i < k ; i++){ vector<ll> akt = zloz(tab[i],perm); if (aktperm.find(akt) == aktperm.end()){ aktperm.insert(akt); Q.push(akt); } } } ll licznik = 0; for (auto j : aktperm){ //for (ll x : j) cout<<x<<" "; //cout<<"\n"; licznik += count_inversions(j); } cout<<(licznik*fastpot(aktperm.size(),mod-2))%mod<<"\n"; return 0; }
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 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 | #include <bits/stdc++.h> using namespace std; typedef long long ll; ll n,k; set<vector<ll> > aktperm; vector<ll> tab[3001]; vector<ll> zloz(vector<ll> A, vector<ll> B){ for (ll i = 0; i < n; i++){ A[i] = B[A[i]-1]; } return A; } const ll mod = 1e9+7; ll fastpot(ll a, ll b){ ll w = 1; while (b){ if (b%2) w = (w*a)%mod; a = (a*a)%mod; b /= 2; } return w%mod; } ll par[3001]; vector<ll> cykl[3001]; vector<pair<ll,ll> > pozycje[3001]; const ll base = (1<<12); ll tree[2*base]; void change(ll v, ll x){ v += base; while (v){ tree[v] = (tree[v]+x+mod)%mod; v /= 2; } } ll query(ll a, ll b){ a += base-1; b += base+1; ll wy = 0; while (b-a > 1){ if (!(a%2)) wy = (wy+tree[a+1]+mod)%mod; if (b%2) wy = (wy+tree[b-1]+mod)%mod; a /= 2; b /= 2; } return wy; } const ll base2 = (1<<4); ll tree2[2*base2]; void change2(ll v, ll x){ v += base2; while (v){ tree2[v] += x; v /= 2; } } ll query2(ll a, ll b){ a += base2-1; b += base2+1; ll wy = 0; while (b-a > 1){ if (!(a%2)) wy += tree2[a+1]; if (b%2) wy += tree2[b-1]; a /= 2; b /= 2; } return wy; } ll count_inversions(vector<ll> & permutacja){ ll wy = 0; for (ll x : permutacja){ wy += query2(x,base2-1); change2(x,1); } for (ll x : permutacja) change2(x,-1); return wy; } ll inv(ll x){ return fastpot(x,mod-2); } vector<ll> onwd[3001][3001]; ll gdzie[3001]; void solve2(){ ll i; ll tablica[n+1]; for (i = 1; i <= n; i++) cin>>tablica[i]; for (i = 1; i <= n; i++){ if (par[i]) continue; par[i] = i; cykl[i].push_back(i); ll x = tablica[i]; while (x != i){ par[x] = i; gdzie[x] = cykl[i].size(); cykl[i].push_back(x); x = tablica[x]; } } ll wy = 0; for (ll a = 1; a <= n; a++){ if (par[a] != a) continue; for (ll b = 1; b <= n; b++){ if (par[b] != b) continue; ll nwd = __gcd(cykl[a].size(),cykl[b].size()); for (i = 0; i < nwd; i++) onwd[b][i].clear(); for (ll i = 0; i < (ll)cykl[b].size(); i++){ ll x = cykl[b][i]; onwd[b][i%nwd].push_back(x); //cout<<"Dodajemy "<<x<<" na "<<b<<" "<<i%nwd<<"\n"; } } ll aktwy = 0; for (ll przes = 0; przes < (ll)cykl[a].size(); przes++){ for (i = 0; i < 2*base; i++) tree[i] = 0; for (i = 1; i <= n; i++){ if (par[i] == a){ ll x = cykl[a][(gdzie[i]+przes)%(cykl[a].size())]; aktwy = (aktwy+query(x,base-1))%mod; } ll nwd = __gcd(cykl[a].size(),cykl[par[i]].size()); for (ll x : onwd[par[i]][(gdzie[i]+przes)%nwd]){ //cout<<x<<" "<<inv(onwd[par[i]][(gdzie[i]+przes)%nwd].size())<<"\n"; change(x,inv(onwd[par[i]][(gdzie[i]+przes)%nwd].size())); } } } aktwy = (aktwy*inv(cykl[a].size()))%mod; wy = (wy+aktwy)%mod; } cout<<wy<<"\n"; } signed main(){ ios_base::sync_with_stdio(0); cin.tie(0); ll i; cin>>n>>k; if (k == 1){ solve2(); return 0; } queue<vector<ll> > Q; for (ll j = 0; j < k; j++){ tab[j].resize(n); for (i = 0; i < n; i++) cin>>tab[j][i]; aktperm.insert(tab[j]); Q.push(tab[j]); } while (Q.size()){ vector<ll> perm = Q.front(); Q.pop(); for (ll i = 0; i < k ; i++){ vector<ll> akt = zloz(tab[i],perm); if (aktperm.find(akt) == aktperm.end()){ aktperm.insert(akt); Q.push(akt); } } } ll licznik = 0; for (auto j : aktperm){ //for (ll x : j) cout<<x<<" "; //cout<<"\n"; licznik += count_inversions(j); } cout<<(licznik*fastpot(aktperm.size(),mod-2))%mod<<"\n"; return 0; } |