2017-sp88-team2-H
从 Trac 迁移的文章
这是从旧校内 Wiki 迁移的文章,可能存在一些样式问题,您可以向 memset0 反馈。
原文章内容如下:
{{{
#include<bits/stdc++.h>
using namespace std;
typedef pair<int, int> pii;
struct Permutation {
vector<int> P; Permutation() {} Permutation(int n){ P.resize(n); }
Permutation inv() const {
Permutation ret(P.size());
for(int i = 0; i < int(P.size()); ++i) ret.P[P[i]] = i;
return ret;
}
int & operator [] (const int & dn) { return P[dn]; }
void resize(const size_t & sz) { P.resize(sz); }
size_t size() const { return P.size(); }
const int & operator [] (const int & dn) const { return P[dn]; }
};
Permutation operator * (const Permutation & a, const Permutation & b) {
Permutation ret(a.size());
for(int i(0); i < (int)a.size(); ++i) ret[i] = b[a[i]];
return ret;
}
typedef vector<Permutation> Bucket;
typedef vector<int> Table; typedef pair<int, int> pii;
int n, m;
vector<Bucket> buckets, bucketsInv; vector<Table> lookupTable;
int fastFilter(const Permutation & g, bool addToGroup = true) {
int n = buckets.size();
Permutation p(g);
for(int i = 0; i < n; ++i) {
int res = lookupTable[i][p[i]];
if(res == -1) {
if(addToGroup) {
buckets[i].push_back(p); bucketsInv[i].push_back(p.inv());
lookupTable[i][p[i]] = (int)buckets[i].size() - 1;
}
return i;
}
p = p * bucketsInv[i][res];// swap(i1, i2);
}
return -1;
}
long long calcTotalSize() {
long long ret = 1;
for(int i(0); i < n; i++) ret *= buckets[i].size();
return ret;
}
bool inGroup(const Permutation & g) { return fastFilter(g, false) == -1; }
void solve(const Bucket & gen, int _n) {
n = _n, m = gen.size();
{
vector<Bucket> _buckets(n); swap(buckets, _buckets);
vector<Bucket> _bucketsInv(n); swap(bucketsInv, _bucketsInv);
vector<Table> _lookupTable(n); swap(lookupTable, _lookupTable);
}
for(int i = 0; i < n; i++) {
lookupTable[i].resize(n);
fill(lookupTable[i].begin(), lookupTable[i].end(), -1);
}
Permutation id(n);
for(int i(0); i < n; i++) id[i] = i;
for(int i = 0; i < n; i++) {
buckets[i].push_back(id); bucketsInv[i].push_back(id);
lookupTable[i][i] = 0;
}
for(int i(0); i < m; i++) fastFilter(gen[i]);
queue<pair<pii, pii> > toUpdate;
for(int i = 0; i < n; i++)
for(int j = i; j < n; j++)
for(int k = 0; k < (int)buckets[i].size(); k++)
for(int l = 0; l < (int)buckets[j].size(); l++)
toUpdate.push(make_pair(pii(i, k), pii(j, l)));
while(!toUpdate.empty()) {
pii a = toUpdate.front().first, b = toUpdate.front().second;
toUpdate.pop();
int res = fastFilter(buckets[a.first][a.second] * buckets[b.first][b.second]);
if(res == -1) continue;
pii newPair(res, (int)buckets[res].size() - 1);
for(int i = 0; i < n; ++i)
for(int j = 0; j < (int)buckets[i].size(); ++j) {
if(i <= res) toUpdate.push(make_pair(pii(i, j), newPair));
if(res <= i) toUpdate.push(make_pair(newPair, pii(i, j)));
}
}
}
int main() {
int m, n;
scanf("%d%d", &m, &n);
Bucket tmp;
for(int i(0); i < m; i++) {
Permutation v(n);
int x;
for(int i(0); i < n; i++) {
scanf("%d", &x);
x--;
v[i] = x;
}
tmp.push_back(v);
}
solve(tmp, n);
cout << calcTotalSize() << endl;
}
}}}
#include<bits/stdc++.h>
using namespace std;
typedef pair<int, int> pii;
struct Permutation {
vector<int> P; Permutation() {} Permutation(int n){ P.resize(n); }
Permutation inv() const {
Permutation ret(P.size());
for(int i = 0; i < int(P.size()); ++i) ret.P[P[i]] = i;
return ret;
}
int & operator [] (const int & dn) { return P[dn]; }
void resize(const size_t & sz) { P.resize(sz); }
size_t size() const { return P.size(); }
const int & operator [] (const int & dn) const { return P[dn]; }
};
Permutation operator * (const Permutation & a, const Permutation & b) {
Permutation ret(a.size());
for(int i(0); i < (int)a.size(); ++i) ret[i] = b[a[i]];
return ret;
}
typedef vector<Permutation> Bucket;
typedef vector<int> Table; typedef pair<int, int> pii;
int n, m;
vector<Bucket> buckets, bucketsInv; vector<Table> lookupTable;
int fastFilter(const Permutation & g, bool addToGroup = true) {
int n = buckets.size();
Permutation p(g);
for(int i = 0; i < n; ++i) {
int res = lookupTable[i][p[i]];
if(res == -1) {
if(addToGroup) {
buckets[i].push_back(p); bucketsInv[i].push_back(p.inv());
lookupTable[i][p[i]] = (int)buckets[i].size() - 1;
}
return i;
}
p = p * bucketsInv[i][res];// swap(i1, i2);
}
return -1;
}
long long calcTotalSize() {
long long ret = 1;
for(int i(0); i < n; i++) ret *= buckets[i].size();
return ret;
}
bool inGroup(const Permutation & g) { return fastFilter(g, false) == -1; }
void solve(const Bucket & gen, int _n) {
n = _n, m = gen.size();
{
vector<Bucket> _buckets(n); swap(buckets, _buckets);
vector<Bucket> _bucketsInv(n); swap(bucketsInv, _bucketsInv);
vector<Table> _lookupTable(n); swap(lookupTable, _lookupTable);
}
for(int i = 0; i < n; i++) {
lookupTable[i].resize(n);
fill(lookupTable[i].begin(), lookupTable[i].end(), -1);
}
Permutation id(n);
for(int i(0); i < n; i++) id[i] = i;
for(int i = 0; i < n; i++) {
buckets[i].push_back(id); bucketsInv[i].push_back(id);
lookupTable[i][i] = 0;
}
for(int i(0); i < m; i++) fastFilter(gen[i]);
queue<pair<pii, pii> > toUpdate;
for(int i = 0; i < n; i++)
for(int j = i; j < n; j++)
for(int k = 0; k < (int)buckets[i].size(); k++)
for(int l = 0; l < (int)buckets[j].size(); l++)
toUpdate.push(make_pair(pii(i, k), pii(j, l)));
while(!toUpdate.empty()) {
pii a = toUpdate.front().first, b = toUpdate.front().second;
toUpdate.pop();
int res = fastFilter(buckets[a.first][a.second] * buckets[b.first][b.second]);
if(res == -1) continue;
pii newPair(res, (int)buckets[res].size() - 1);
for(int i = 0; i < n; ++i)
for(int j = 0; j < (int)buckets[i].size(); ++j) {
if(i <= res) toUpdate.push(make_pair(pii(i, j), newPair));
if(res <= i) toUpdate.push(make_pair(newPair, pii(i, j)));
}
}
}
int main() {
int m, n;
scanf("%d%d", &m, &n);
Bucket tmp;
for(int i(0); i < m; i++) {
Permutation v(n);
int x;
for(int i(0); i < n; i++) {
scanf("%d", &x);
x--;
v[i] = x;
}
tmp.push_back(v);
}
solve(tmp, n);
cout << calcTotalSize() << endl;
}