結果

問題 No.1907 DETERMINATION
ユーザー Noszály ÁronNoszály Áron
提出日時 2023-10-16 01:17:37
言語 C++14
(gcc 12.3.0 + boost 1.83.0)
結果
AC  
実行時間 1,264 ms / 4,000 ms
コード長 7,917 bytes
コンパイル時間 3,424 ms
コンパイル使用メモリ 168,136 KB
実行使用メモリ 9,088 KB
最終ジャッジ日時 2024-09-16 22:09:28
合計ジャッジ時間 39,575 ms
ジャッジサーバーID
(参考情報)
judge6 / judge1
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 2 ms
5,248 KB
testcase_01 AC 2 ms
5,248 KB
testcase_02 AC 2 ms
5,376 KB
testcase_03 AC 3 ms
5,376 KB
testcase_04 AC 2 ms
5,376 KB
testcase_05 AC 2 ms
5,376 KB
testcase_06 AC 2 ms
5,376 KB
testcase_07 AC 267 ms
6,520 KB
testcase_08 AC 107 ms
5,376 KB
testcase_09 AC 182 ms
5,888 KB
testcase_10 AC 769 ms
8,960 KB
testcase_11 AC 335 ms
8,064 KB
testcase_12 AC 655 ms
8,704 KB
testcase_13 AC 620 ms
8,576 KB
testcase_14 AC 591 ms
8,832 KB
testcase_15 AC 123 ms
5,632 KB
testcase_16 AC 41 ms
5,376 KB
testcase_17 AC 739 ms
8,704 KB
testcase_18 AC 463 ms
7,296 KB
testcase_19 AC 11 ms
5,376 KB
testcase_20 AC 667 ms
8,704 KB
testcase_21 AC 56 ms
5,376 KB
testcase_22 AC 767 ms
8,192 KB
testcase_23 AC 848 ms
8,704 KB
testcase_24 AC 207 ms
5,888 KB
testcase_25 AC 2 ms
5,376 KB
testcase_26 AC 649 ms
8,832 KB
testcase_27 AC 1,021 ms
8,832 KB
testcase_28 AC 953 ms
8,832 KB
testcase_29 AC 965 ms
8,960 KB
testcase_30 AC 2 ms
5,376 KB
testcase_31 AC 674 ms
8,960 KB
testcase_32 AC 645 ms
8,960 KB
testcase_33 AC 648 ms
8,960 KB
testcase_34 AC 651 ms
8,832 KB
testcase_35 AC 2 ms
5,376 KB
testcase_36 AC 2 ms
5,376 KB
testcase_37 AC 2 ms
5,376 KB
testcase_38 AC 646 ms
9,088 KB
testcase_39 AC 646 ms
8,960 KB
testcase_40 AC 1,264 ms
8,960 KB
testcase_41 AC 645 ms
8,960 KB
testcase_42 AC 1,262 ms
8,832 KB
testcase_43 AC 1,264 ms
8,960 KB
testcase_44 AC 834 ms
8,960 KB
testcase_45 AC 950 ms
8,960 KB
testcase_46 AC 650 ms
8,832 KB
testcase_47 AC 642 ms
8,960 KB
testcase_48 AC 645 ms
8,960 KB
testcase_49 AC 734 ms
8,960 KB
testcase_50 AC 645 ms
8,960 KB
testcase_51 AC 646 ms
8,960 KB
testcase_52 AC 2 ms
5,376 KB
testcase_53 AC 1,007 ms
8,192 KB
testcase_54 AC 998 ms
8,320 KB
testcase_55 AC 2 ms
5,376 KB
testcase_56 AC 1,002 ms
8,320 KB
testcase_57 AC 999 ms
8,320 KB
testcase_58 AC 701 ms
8,832 KB
testcase_59 AC 414 ms
8,960 KB
testcase_60 AC 416 ms
9,088 KB
testcase_61 AC 578 ms
9,088 KB
testcase_62 AC 417 ms
8,960 KB
testcase_63 AC 648 ms
8,832 KB
testcase_64 AC 2 ms
5,376 KB
testcase_65 AC 2 ms
5,376 KB
testcase_66 AC 2 ms
5,376 KB
権限があれば一括ダウンロードができます

ソースコード

diff #

#include<iostream>
#include<vector>
#include<map>
#include<set>
#include<cassert>
#include<unordered_map>
#include<unordered_set>
#include<functional>
#include<queue>
#include<stack>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<sstream>
#include<iomanip>
#include<cstdio>
#include<cstdlib>
#include<numeric>
#include<random>
#include<chrono>
#include<bitset>
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/tree_policy.hpp>
using namespace std;
using namespace __gnu_pbds;

#define all(x) (x).begin(), (x).end()
#define pb push_back
#define eb emplace_back
#define xx first
#define yy second
#define sz(x) (int)(x).size()
#define gc getchar
#define IO ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define mp make_pair
#define ins insert

#ifndef ONLINE_JUDGE
#  define LOG(x) (cerr << #x << " = " << (x) << endl)
#else
#  define LOG(x) ((void)0)
#endif

using ll = long long;
using ull = unsigned long long ;
using ld = long double ;
using str = string;
using ordered_set=tree<pair<int,int>, null_type, less<pair<int,int>>, rb_tree_tag, tree_order_statistics_node_update>;

const double PI=acos(-1);
const ll INF = 1LL<<62;
const ll MINF = -(1LL<<62);

template<typename T> T getint() {
    T val=0;
    char c;
    
    bool neg=false;
    while((c=gc()) && !(c>='0' && c<='9')) {
        neg|=c=='-';
    }

    do {
        val=(val*10)+c-'0';
    } while((c=gc()) && (c>='0' && c<='9'));

    return val*(neg?-1:1);
}

//mt19937 rng(chrono::steady_clock::now().time_since_epoch().count()); uniform_int_distribution<int>(0, n-1)(rng)

const ll mod=998244353;

template<int m>
struct modular {
    int64_t r;
    modular() : r(0) {}
    modular(int64_t rr) : r(rr) {if(abs(r) >= m) r %= m; if(r < 0) r += m;}
    modular inv() const {return bpow(*this, m - 2);}
    modular operator * (const modular &t) const {return (r * t.r) % m;}
    modular operator / (const modular &t) const {return *this * t.inv();}
    modular operator += (const modular &t) {r += t.r; if(r >= m) r -= m; return *this;}
    modular operator -= (const modular &t) {r -= t.r; if(r < 0) r += m; return *this;}
    modular operator + (const modular &t) const {return modular(*this) += t;}
    modular operator - (const modular &t) const {return modular(*this) -= t;}
    modular operator *= (const modular &t) {return *this = *this * t;}
    modular operator /= (const modular &t) {return *this = *this / t;}
    
    bool operator == (const modular &t) const {return r == t.r;}
    bool operator != (const modular &t) const {return r != t.r;}
    
    operator int64_t() const {return r;}

     
    int64_t bpow(int64_t a, int64_t b) const {
		int64_t res=1;
		while(b) {
			if(b&1) res=(res*a)%m;
			a=(a*a)%m;
			b/=2;
		}
		return res;
	}
};

using Mint = modular<mod>;
using matrix = vector<vector<Mint>>;

ostream& operator<<(ostream& os, matrix M) {
    for(auto& i:M) {
        for(auto& j:i) {
            os<<j<<" ";
        }
        os<<"\n";
    }
    return os;
}
 

void swap_row(matrix& M, int i, int j) {
    assert(i!=j);
    for(int k=0;k<sz(M);++k) {
        swap(M[i][k], M[j][k]);
    }
} 

void swap_col(matrix& M, int i, int j) {
    assert(i!=j);
    for(int k=0;k<sz(M);++k) {
        swap(M[k][i], M[k][j]);
    }
}

void row_op(matrix& M, int i, int j, Mint c) {
    for(int k=0;k<sz(M);++k) {
        M[i][k]+=M[j][k]*c;
    }
}

void col_op(matrix& M, int i, int j, Mint c) {
    for(int k=0;k<sz(M);++k) {
        M[k][i]+=M[k][j]*c;
    }
}

void make_upper_heisenberg(matrix& M) {
    const int n=M.size();
    for(int col=0;col<n-2;++col) {
        int piv=-1;
        for(int row=col+1;row<n;++row) {
            if(M[row][col]!=Mint(0)) {
                piv=row;
                break;
            }
        }
        
        if(piv<0) continue ;
        if(col+1!=piv) {
            swap_row(M, col+1, piv);
            swap_col(M, col+1, piv);
        }
    
        auto inv=M[col+1][col].inv();
        for(int i=col+2;i<n;++i) {
            auto coeff=-M[i][col]*inv;
            row_op(M, i, col+1, coeff); //unitér legyen
            col_op(M, col+1, i, -coeff);
        }
    }
}

vector<Mint> char_poly(matrix& M) {
    const int n=sz(M);
    
    make_upper_heisenberg(M);
    
    vector<vector<Mint>> p(n+1);
    p[0]={1};

    //det(Ix-M)
    //kifejtés miatt: P[i+1]=1*(-P[i]*M(i,i)+xP[i])-\sum j=0..i-1 (P[j]*M(j,i)* prod M(j+1..i,j..i-1))
    for(int i=0;i<n;++i) { 
        p[i+1].assign(i+2, 0);
        for(int j=0;j<sz(p[i]);++j) p[i+1][j]-=p[i][j]*M[i][i];
        for(int j=0;j<sz(p[i]);++j) p[i+1][j+1]+=p[i][j];
        
        Mint mul=1;
        for(int j=i-1;j>=0;j--) {
            mul*=M[j+1][j];
            Mint hb=-M[j][i]*mul;
            for(int k=0;k<sz(p[j]);++k) p[i+1][k]+=hb*p[j][k];
        }
    }
    
    return p[n];
}

//det(M0+M1x) kiszámítása
vector<Mint> det_linear(matrix M0, matrix M1) {
    //sor és oszlop műveletekkel M1-et I-vé transzformáljuk det(M0+M1x)=1/(det(A)*det(B))*det(Ix+AM0B) alakra hozzuk => -AM0B karakterisztikus polinomja a megoldás
    //ha nem reguláris M1 "M0-ból hozunk át oszlopokat"
    const int N=M0.size();
    Mint invdetAB=1;
    int powx=0;
    for(int p=0;p<N;++p) {
        int piv=-1;
        for(int row=p;row<N;++row) {
            if(M1[row][p]!=Mint(0)) {
                piv=row;
                break ;
            }
        }
        if(piv<0) {
            powx++;
            if(powx>N) return vector<Mint>(N+1);
            
            for(int i=0;i<p;++i) {
                Mint val=-M1[i][p];
                col_op(M0, p, i, val);
                col_op(M1, p, i, val); //felesleges valójában
            }
            for(int i=0;i<N;++i) swap(M0[i][p], M1[i][p]);
            p--;
            
            continue ;
        }
        
        if(p!=piv) {
            swap_row(M0, piv, p);
            swap_row(M1, piv, p);
            invdetAB*=-1;
        }
        
        Mint v=M1[p][p];
        Mint vinv=v.inv();
        
        invdetAB*=v;
        for(int col=0;col<N;++col) {
            M0[p][col]*=vinv;
            M1[p][col]*=vinv;
        }
        
        for(int row=0;row<N;++row) {
            if(row!=p) {
                Mint val=-M1[row][p];
                row_op(M1, row, p, val);
                row_op(M0, row, p, val);
            }
        }
    }
    
    for(auto& i:M0) 
        for(auto& j:i) 
            j=-j;
    
    auto res=char_poly(M0);
    for(auto& i:res) i*=invdetAB;
    
    res.erase(res.begin(), res.begin()+powx);
    res.resize(N+1);
    
    return res;
}
 

void test_make_upper_hessenberg() {
    matrix m;
    
    m={{1,1},{1,1}};
    make_upper_heisenberg(m);
    assert((m==matrix{{1,1},{1,1}}));
    
    m={{1,2,3},{3,4,5},{0,9,9}};
    make_upper_heisenberg(m);
    assert((m==matrix{{{1,2,3},{3,4,5},{0,9,9}}}));
    
    m={{1,2,3},{4,5,6},{7,8,9}};
    make_upper_heisenberg(m);
    
    m={{1,2},{3,4}};
    assert((char_poly(m)==vector<Mint>{998244351,998244348,1}));
    //~ for(auto i:char_poly(m)) cerr<<i<<" ";cerr<<"\n";
}


int main() {
    IO;
    //~ test_make_upper_hessenberg();
    //~ int n;
    //~ cin>>n;
    //~ matrix m(n);
    //~ for(int i=0;i<n;++i) {
        //~ m[i].resize(n);
        //~ for(int j=0;j<n;++j) {
            //~ ll x;
            //~ cin>>x;
            //~ m[i][j]=x;
        //~ }
    //~ }
    
    //~ for(auto i:char_poly(m)) {
        //~ cout<<i<<" ";
    //~ }cout<<"\n";
    
    int n;
    cin>>n;
    matrix M0(n), M1(n);
    for(int i=0;i<n;++i) {
        M0[i].resize(n);
        for(int j=0;j<n;++j) {
            ll x;
            cin>>x;
            M0[i][j]=x;
        }
    }
    
    for(int i=0;i<n;++i) {
        M1[i].resize(n);
        for(int j=0;j<n;++j) {
            ll x;
            cin>>x;
            M1[i][j]=x;
        }
    }
    
    for(auto i:det_linear(M0, M1)) cout<<i<<"\n";
    
    
    return 0;
}
0