QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#189638 | #4907. djq 学生物 | sigma425 | 0 | 1461ms | 78736kb | C++23 | 16.5kb | 2023-09-27 18:55:54 | 2023-09-27 18:55:55 |
Judging History
answer
// #pragma GCC target("avx,avx2")
// #pragma GCC optimize("Ofast")
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using uint = unsigned int;
using ull = unsigned long long;
#define rep(i,n) for(int i=0;i<int(n);i++)
#define rep1(i,n) for(int i=1;i<=int(n);i++)
#define per(i,n) for(int i=int(n)-1;i>=0;i--)
#define per1(i,n) for(int i=int(n);i>0;i--)
#define all(c) c.begin(),c.end()
#define si(x) int(x.size())
#define pb push_back
#define eb emplace_back
#define fs first
#define sc second
template<class T> using V = vector<T>;
template<class T> using VV = vector<vector<T>>;
template<class T,class U> bool chmax(T& x, U y){
if(x<y){ x=y; return true; }
return false;
}
template<class T,class U> bool chmin(T& x, U y){
if(y<x){ x=y; return true; }
return false;
}
template<class T> void mkuni(V<T>& v){sort(all(v));v.erase(unique(all(v)),v.end());}
template<class T> int lwb(const V<T>& v, const T& a){return lower_bound(all(v),a) - v.begin();}
template<class T>
V<T> Vec(size_t a) {
return V<T>(a);
}
template<class T, class... Ts>
auto Vec(size_t a, Ts... ts) {
return V<decltype(Vec<T>(ts...))>(a, Vec<T>(ts...));
}
template<class S,class T> ostream& operator<<(ostream& o,const pair<S,T> &p){
return o<<"("<<p.fs<<","<<p.sc<<")";
}
template<class T> ostream& operator<<(ostream& o,const vector<T> &vc){
o<<"{";
for(const T& v:vc) o<<v<<",";
o<<"}";
return o;
}
constexpr ll TEN(int n) { return (n == 0) ? 1 : 10 * TEN(n-1); }
#ifdef LOCAL
#define show(x) cerr << "LINE" << __LINE__ << " : " << #x << " = " << (x) << endl
void dmpr(ostream& os){os<<endl;}
template<class T,class... Args>
void dmpr(ostream&os,const T&t,const Args&... args){
os<<t<<" ~ ";
dmpr(os,args...);
}
#define shows(...) cerr << "LINE" << __LINE__ << " : ";dmpr(cerr,##__VA_ARGS__)
#define dump(x) cerr << "LINE" << __LINE__ << " : " << #x << " = {"; \
for(auto v: x) cerr << v << ","; cerr << "}" << endl;
#else
#define show(x) void(0)
#define dump(x) void(0)
#define shows(...) void(0)
#endif
template<class D> D divFloor(D a, D b){
return a / b - (((a ^ b) < 0 && a % b != 0) ? 1 : 0);
}
template<class D> D divCeil(D a, D b) {
return a / b + (((a ^ b) > 0 && a % b != 0) ? 1 : 0);
}
template<unsigned int mod_>
struct ModInt{
using uint = unsigned int;
using ll = long long;
using ull = unsigned long long;
constexpr static uint mod = mod_;
uint v;
ModInt():v(0){}
ModInt(ll _v):v(normS(_v%mod+mod)){}
explicit operator bool() const {return v!=0;}
static uint normS(const uint &x){return (x<mod)?x:x-mod;} // [0 , 2*mod-1] -> [0 , mod-1]
static ModInt make(const uint &x){ModInt m; m.v=x; return m;}
ModInt operator+(const ModInt& b) const { return make(normS(v+b.v));}
ModInt operator-(const ModInt& b) const { return make(normS(v+mod-b.v));}
ModInt operator-() const { return make(normS(mod-v)); }
ModInt operator*(const ModInt& b) const { return make((ull)v*b.v%mod);}
ModInt operator/(const ModInt& b) const { return *this*b.inv();}
ModInt& operator+=(const ModInt& b){ return *this=*this+b;}
ModInt& operator-=(const ModInt& b){ return *this=*this-b;}
ModInt& operator*=(const ModInt& b){ return *this=*this*b;}
ModInt& operator/=(const ModInt& b){ return *this=*this/b;}
ModInt& operator++(int){ return *this=*this+1;}
ModInt& operator--(int){ return *this=*this-1;}
template<class T> friend ModInt operator+(T a, const ModInt& b){ return (ModInt(a) += b);}
template<class T> friend ModInt operator-(T a, const ModInt& b){ return (ModInt(a) -= b);}
template<class T> friend ModInt operator*(T a, const ModInt& b){ return (ModInt(a) *= b);}
template<class T> friend ModInt operator/(T a, const ModInt& b){ return (ModInt(a) /= b);}
ModInt pow(ll p) const {
if(p<0) return inv().pow(-p);
ModInt a = 1;
ModInt x = *this;
while(p){
if(p&1) a *= x;
x *= x;
p >>= 1;
}
return a;
}
ModInt inv() const { // should be prime
return pow(mod-2);
}
// ll extgcd(ll a,ll b,ll &x,ll &y) const{
// ll p[]={a,1,0},q[]={b,0,1};
// while(*q){
// ll t=*p/ *q;
// rep(i,3) swap(p[i]-=t*q[i],q[i]);
// }
// if(p[0]<0) rep(i,3) p[i]=-p[i];
// x=p[1],y=p[2];
// return p[0];
// }
// ModInt inv() const {
// ll x,y;
// extgcd(v,mod,x,y);
// return make(normS(x+mod));
// }
bool operator==(const ModInt& b) const { return v==b.v;}
bool operator!=(const ModInt& b) const { return v!=b.v;}
bool operator<(const ModInt& b) const { return v<b.v;}
friend istream& operator>>(istream &o,ModInt& x){
ll tmp;
o>>tmp;
x=ModInt(tmp);
return o;
}
friend ostream& operator<<(ostream &o,const ModInt& x){ return o<<x.v;}
};
using mint = ModInt<998244353>;
//using mint = ModInt<1000000007>;
template<class T>
struct Matrix: public vector<vector<T>>{
Matrix(){}
explicit Matrix(int n) : vector<vector<T>>(n,vector<T>(n)){}
Matrix(int h,int w) : vector<vector<T>>(h,vector<T>(w)){}
Matrix(const vector<vector<T>>& a):vector<vector<T>>(a){}
static Matrix E(int n){
Matrix a(n,n);
rep(i,n) a[i][i] = 1;
return a;
}
int h() const { return (*this).size(); }
int w() const { return (*this)[0].size(); }
Matrix operator+(const Matrix& r) const {
assert(h() == r.h() && w() == r.w());
int H = h(), W = w();
Matrix z(H,W);
rep(i,H) rep(j,W) z[i][j] = (*this)[i][j] + r[i][j];
return z;
}
Matrix operator-(const Matrix& r) const {
assert(h() == r.h() && w() == r.w());
int H = h(), W = w();
Matrix z(H,W);
rep(i,H) rep(j,W) z[i][j] = (*this)[i][j] - r[i][j];
return z;
}
Matrix operator*(const Matrix& r) const {
assert(w() == r.h());
int A = h(), B = w(), C = r.w();
Matrix z(A,C);
rep(i,A) rep(k,B) rep(j,C) z[i][j] += (*this)[i][k] * r[k][j];
return z;
}
Matrix& operator+=(const Matrix& r){return (*this)=(*this)+r;}
Matrix& operator-=(const Matrix& r){return (*this)=(*this)-r;}
Matrix& operator*=(const Matrix& r){return (*this)=(*this)*r;}
Matrix& operator*=(const T& r){
rep(i,h()) rep(j,w()) (*this)[i][j] *= r;
return *this;
}
Matrix operator*(const T& r) const {
return Matrix(*this) *= r;
}
Matrix pow(ll p) const {
assert(h() == w());
Matrix res = E(h());
Matrix x = *this;
while(p){
if(p&1) res *= x;
x *= x;
p >>= 1;
}
return res;
}
friend ostream& operator<<(ostream &o,const Matrix& A){
rep(i,A.h()){
rep(j,A.w()) o << A[i][j]<<" ";
o << endl;
}
return o;
}
T trace(){
T t = 0;
rep(i,h()) t += (*this)[i][i];
return t;
}
};
using Mat = Matrix<mint>;
V<mint> fact,ifact,invs;
mint Choose(int a,int b){
if(b<0 || a<b) return 0;
return fact[a] * ifact[b] * ifact[a-b];
}
void InitFact(int N){ //[0,N]
N++;
fact.resize(N);
ifact.resize(N);
invs.resize(N);
fact[0] = 1;
rep1(i,N-1) fact[i] = fact[i-1] * i;
ifact[N-1] = fact[N-1].inv();
for(int i=N-2;i>=0;i--) ifact[i] = ifact[i+1] * (i+1);
rep1(i,N-1) invs[i] = fact[i-1] * ifact[i];
}
template<class T>
T rnd(T l,T r){ //[l,r)
using D = uniform_int_distribution<T>;
static random_device rd;
static mt19937 gen(rd());
return D(l,r-1)(gen);
}
template<class T>
T rnd(T n){ //[0,n)
return rnd(T(0),n);
}
/*
inversion
なければ {{}}
*/
template<class T>
vector<vector<T>> Matrixinv(vector<vector<T>> a){
assert(a.size() == a[0].size());
vector<vector<T>> no;
int n = a.size();
vector<int> ih(n,-1), jh(n,-1);
rep(k,n){
for(int i=k;i<n;i++) if(ih[k] == -1){
for(int j=k;j<n;j++) if(a[i][j]){
ih[k] = i, jh[k] = j; break;
}
}
if(ih[k] == -1) return no;
rep(j,n) swap(a[k][j],a[ih[k]][j]);
rep(i,n) swap(a[i][k],a[i][jh[k]]);
if(!a[k][k]) return no;
a[k][k] = a[k][k].inv();
rep(i,n) if(i != k) a[k][i] *= a[k][k];
rep(i,n) if(i != k){
rep(j,n) if(j != k){
a[i][j] -= a[i][k]*a[k][j];
}
}
rep(i,n) if(i != k) a[i][k] *= -a[k][k];
}
per(k,n){
rep(j,n) swap(a[k][j],a[jh[k]][j]);
rep(i,n) swap(a[i][k],a[i][ih[k]]);
}
return a;
}
/*
テンソル積 (クロネッカー積)
A⊗B =[a{0,0}B .. a_{0,w-1}B]
[a{1,0}B .. a_{1,w-1}B]
:
Aの1マスを分割してBにするイメージ
*/
template<class T>
vector<vector<T>> tensor(vector<vector<T>> A, vector<vector<T>> B){
int ah = si(A), aw = si(A[0]), bh = si(B), bw = si(B[0]);
vector<vector<T>> C(ah*bh,vector<T>(aw*bw));
rep(ai,ah) rep(aj,aw){
rep(bi,bh) rep(bj,bw){
C[ai*bh+bi][aj*bw+bj] = A[ai][aj] * B[bi][bj];
}
}
return C;
}
VV<int> perms;
VV<int> op;
V<int> inv;
VV<int> types;
V<int> type;
/*
charTable[irred rep][cycle type]
Sn の表現論なので irred rep の方も cycle type で indexed できるが、
irred rep の順番は自由にしていい
cycle type の index は type[] と一致してないといけない
S_20 くらいまでの表を生成してくれるサイト: https://www.jgibson.id.au/articles/characters/
https://math.mit.edu/events/stanley70/Site/Slides/Early.pdf
この表の順番は type[] と一致してる
*/
VV<Mat> irredReps;
V<int> dims;
/*
でかい順にならべたときの辞書順
{{1,1,1,1,1,},{2,1,1,1,},{2,2,1,},{3,1,1,},{3,2,},{4,1,},{5,},}
*/
void enumTypes(int n){
V<int> a;
auto dfs = [&](auto&& self, int s, int p) -> void {
if(s == 0){
types.pb(a);
return;
}
rep1(i,min(p,s)){
a.pb(i);
self(self,s-i,i);
a.pop_back();
}
};
dfs(dfs,n,n);
// show(types);
}
void initPerms(int n){
V<int> a(n); iota(all(a),0);
do{
perms.pb(a);
}while(next_permutation(all(a)));
int m = si(perms);
op = VV<int>(m,V<int>(m));
inv = V<int>(m);
rep(i,m) rep(j,m){
V<int> ij(n);
rep(k,n) ij[k] = perms[i][perms[j][k]];
op[i][j] = find(all(perms),ij) - perms.begin();
if(op[i][j] == 0) inv[i] = j;
}
enumTypes(n);
rep(i,m){
V<int> b = perms[i];
V<bool> done(n);
V<int> cs;
rep(j,n) if(!done[j]){
int c = 0;
int x = j;
while(!done[x]){
done[x] = true;
c++;
x = b[x];
}
cs.pb(c);
}
sort(all(cs),greater<int>());
type.pb(lwb(types,cs));
}
// show(perms);show(op);show(type);
}
void initIrredReps(){
irredReps.resize(3); // num of irred reps
for(auto& irred: irredReps) irred.resize(6);
// 012 021 102 120 201 210
using M = VV<mint>;
rep(j,6) irredReps[0][j] = VV<mint>{{1}};
irredReps[1] = {M{{1}},M{{-1}},M{{-1}},M{{1}},M{{1}},M{{-1}}};
irredReps[2][0] = M{{1,0},{0,1}};
irredReps[2][1] = M{{1,0},{1,-1}};
irredReps[2][2] = M{{-1,1},{0,1}};
irredReps[2][3] = M{{0,-1},{1,-1}};
irredReps[2][4] = M{{-1,1},{-1,0}};
irredReps[2][5] = M{{0,-1},{-1,0}};
for(auto& irred: irredReps){
rep(i,6) rep(j,6) assert(irred[i] * irred[j] == irred[op[i][j]]);
}
rep(s,si(irredReps)){
dims.pb(irredReps[s][0].h());
}
}
// vector<Mat> FT1(V<mint> a){
// vector<Mat> za;
// for(auto& irrep: irredReps){
// int k = irrep[0].h();
// Mat sm(k);
// rep(v,6) sm += irrep[v] * a[v];
// za.pb(sm);
// }
// return za;
// }
// V<mint> iFT1(vector<Mat> za){
// vector<mint> a(6);
// rep(v,6){
// rep(s,3) a[v] += dims[s] * (irredReps[s][inv[v]] * za[s]).trace();
// }
// mint coef = mint(6).inv();
// rep(i,6) a[i] *= coef;
// return a;
// }
vector<Mat> FT1(vector<Mat> a){
vector<Mat> za;
for(auto& irrep: irredReps){
int k = a[0].h() * irrep[0].h();
Mat sm(k);
rep(v,6) sm += tensor(a[v],irrep[v]);
za.pb(sm);
}
return za;
}
/*
Mat za はテンソルなわけだが、最後に右からかけた行列がd*d で、これを一点に圧縮するイメージ
za の各 d*d ブロックにたいして、1次元バージョンのやつをやる
*/
vector<Mat> iFT1(vector<Mat> za){
int n = si(za[0]) / dims[0];
vector<Mat> a(6,Mat(n));
rep(s,3) rep(v,6){
int d = dims[s];
rep(i,n) rep(j,n){
Mat block(d);
rep(ii,d) rep(jj,d) block[ii][jj] = za[s][i*d+ii][j*d+jj];
a[v][i][j] += dims[s] * (block * irredReps[s][inv[v]]).trace();
}
}
mint coef = mint(6).inv();
rep(i,6) a[i] *= coef;
return a;
}
// V<mint> conv1(V<mint> a, V<mint> b){
// vector<Mat> za = FT1(a), zb = FT1(b);
// rep(s,si(za)) za[s] *= zb[s];
// return iFT1(za);
// }
// V<mint> conv1_brute(V<mint> a, V<mint> b){
// int n = si(a);
// V<mint> c(n);
// rep(i,n) rep(j,n) c[op[i][j]] += a[i]*b[j];
// return c;
// }
template<class T>
struct ndarray{
int S;
vector<T> v;
vector<int> ms;
vector<int> coefs;
ndarray(){}
ndarray(vector<int> ms_):ms(ms_),coefs(si(ms_),1){
for(int d=si(ms)-2;d>=0;d--) coefs[d] = coefs[d+1] * ms[d+1];
S = 1; rep(d,si(ms)) S *= ms[d];
v.resize(S);
}
int id(const vector<int>& is) const {
int s = 0;
for(int d=0;d<si(ms);d++) s += is[d] * coefs[d];
return s;
}
vector<int> di(int i){
V<int> is(si(ms));
rep(d,si(ms)){
is[d] = i/coefs[d];
i %= coefs[d];
}
return is;
}
T& operator[](const vector<int>& is){
return v[id(is)];
}
const T& operator[](const vector<int>& is) const {
return v[id(is)];
}
T& operator[](int i){
return v[i];
}
const T& operator[](int i) const {
return v[i];
}
friend ostream& operator<<(ostream &o,const ndarray& a){
return o << a.v;
}
int size(){
return S;
}
int dim(){
return si(ms);
}
};
template<class T> using arr = ndarray<T>;
arr<Mat> FT(arr<mint> a_){
arr<Mat> a(a_.ms); rep(i,a.size()) a[i] = VV<mint>{{a_[i]}};
int n = a.dim();
rep(d,n){
// d次元目を変換
// a[3][3][0,..,5][6][6] -> a[3][3][0,..,2][6][6]
V<int> nms = a.ms; nms[d] = 3;
arr<Mat> na(nms);
int S = a.size();
int D = 1; rep(_,n-1-d) D *= 6;
rep(s,S) if(a.di(s)[d] == 0){
V<Mat> slice(6);
rep(i,6) slice[i] = a[s+D*i];
V<Mat> zslice = FT1(slice);
V<int> is = a.di(s);
rep(i,3){
is[d] = i;
na[is] = zslice[i];
}
}
a = na;
}
return a;
}
arr<mint> iFT(arr<Mat> a){
int n = a.dim();
per(d,n){
// d次元目を逆変換
// a[3][3][0,..,5][6][6] <- a[3][3][0,..,2][6][6]
V<int> nms = a.ms; nms[d] = 6;
arr<Mat> na(nms);
int S = a.size();
int D = 1; rep(_,n-1-d) D *= 6;
rep(s,S) if(a.di(s)[d] == 0){
V<Mat> zslice(3);
rep(i,3) zslice[i] = a[s+D*i];
V<Mat> slice = iFT1(zslice);
V<int> is = a.di(s);
rep(i,6){
is[d] = i;
na[is] = slice[i];
}
}
a = na;
}
arr<mint> res(a.ms);
rep(i,a.size()) res[i] = a[i][0][0];
return res;
}
arr<mint> conv(arr<mint> a, arr<mint> b){
arr<Mat> za = FT(a), zb = FT(b);
rep(i,za.size()) za[i] *= zb[i];
return iFT(za);
}
arr<mint> conv_brute(arr<mint> a, arr<mint> b){
int S = a.size();
int n=0;
{
int x = S;
while(x>1){
x/=6;
n++;
}
}
arr<mint> c(V<int>(n,6));
rep(i,S) rep(j,S){
auto is = c.di(i);
auto js = c.di(j);
V<int> ks(si(is));
rep(_,si(ks)) ks[_] = op[is[_]][js[_]];
c[ks] += a[i]*b[j];
}
return c;
}
void TEST(){
if(false){
int n; cin >> n;
V<int> ms(n,6);
arr<mint> a(ms);
rep(i,a.size()) a[i] = rnd(2);
auto za = FT(a);
auto aa = iFT(za);
cerr << a << endl;
cerr << za << endl;
cerr << aa << endl;
assert(a.v == aa.v);
exit(0);
}
if(false){
int n; cin >> n;
V<int> ms(n,6);
arr<mint> a(ms),b(ms);
rep(i,a.size()) a[i] = rnd(2);
rep(i,b.size()) b[i] = rnd(2);
auto za = FT(a);
auto aa = iFT(za);
assert(a.v == aa.v);
cerr << conv(a,b) << endl;
cerr << conv_brute(a,b) << endl;
exit(0);
}
// while(true){
// V<mint> a(6),b(6);
// rep(i,6) cin >> a[i];
// rep(i,6) cin >> b[i];
// show(conv1_brute(a,b));
// show(conv1(a,b));
// }
// while(true){
// V<mint> a(6); rep(i,6) cin >> a[i];
// auto za = FT1(a);
// show(za);
// auto aa = iFT1(za);
// show(aa);
// }
}
int main(){
cin.tie(0);
ios::sync_with_stdio(false); //DON'T USE scanf/printf/puts !!
cout << fixed << setprecision(20);
initPerms(3);
initIrredReps();
// cerr << "OK" << endl;
// TEST();
int n; cin >> n;
int S = 1; rep(_,n) S *= 6;
// arr<mint> in(V<int>(n,6)); rep(i,S) cin >> in[i];
arr<mint> in(V<int>(n,6)); rep(i,S) in[i] = rnd(114514);
// ans = p/(1-(1-p)f) = inv(M-in)
mint M = accumulate(all(in.v),mint(0)) + 1;
arr<mint> f(V<int>(n,6)); rep(i,S) f[i] = -in[i];
f[0] += M;
auto zf = FT(f);
// h = id, zh = 単位行列からなるやつら
arr<Mat> zg(zf.ms);
rep(i,zf.size()){
zg[i] = Matrixinv(zf[i]);
if(zg[i].empty()){
cout << -1 << endl; return 0;
}
}
auto g = iFT(zg);
// cerr << g << endl;
// cerr << accumulate(all(g.v),mint(0)) << endl;
ll ans = 0;
for(mint v: g.v) ans ^= v.v;
cout << ans << endl;
}
Details
Tip: Click on the bar to expand more detailed information
Subtask #1:
score: 0
Wrong Answer
Test #1:
score: 0
Wrong Answer
time: 1ms
memory: 3640kb
input:
1 10 10 10 10 499122217 499122156
output:
240369097
result:
wrong answer 1st numbers differ - expected: '-1', found: '240369097'
Subtask #2:
score: 0
Skipped
Dependency #1:
0%
Subtask #3:
score: 0
Wrong Answer
Test #8:
score: 0
Wrong Answer
time: 1461ms
memory: 78736kb
input:
7 13237606 0 0 696947386 879320747 0 0 0 0 0 0 0 0 0 0 0 0 0 266959993 0 0 371358373 632390641 0 666960563 0 0 708812199 564325578 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 299649176 0...
output:
921056708
result:
wrong answer 1st numbers differ - expected: '101942575', found: '921056708'
Subtask #4:
score: 0
Skipped
Dependency #1:
0%
Subtask #5:
score: 0
Skipped
Dependency #1:
0%