結果
問題 |
No.3229 Liar Game Comibination
|
ユーザー |
![]() |
提出日時 | 2025-08-10 15:52:06 |
言語 | C++23 (gcc 13.3.0 + boost 1.87.0) |
結果 |
AC
|
実行時間 | 181 ms / 2,000 ms |
コード長 | 3,835 bytes |
コンパイル時間 | 3,935 ms |
コンパイル使用メモリ | 288,984 KB |
実行使用メモリ | 6,272 KB |
最終ジャッジ日時 | 2025-08-10 15:52:13 |
合計ジャッジ時間 | 6,340 ms |
ジャッジサーバーID (参考情報) |
judge2 / judge5 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
sample | AC * 3 |
other | AC * 29 |
ソースコード
#include <bits/stdc++.h> using namespace std; #define ALL(x) (x).begin(), (x).end() #define REP(i, n) for(ll i=0; i<(ll)(n); i++) template<typename T> bool chmax(T& a, T b) { return a<b ? a=b, true : false; } template<typename T> bool chmin(T& a, T b) { return a>b ? a=b, true : false; } using ll=long long; const int INF=1e9+10; const ll INFL=4e18; using VI=vector<int>; using VVI=vector<VI>; using VL=vector<ll>; using VVL=vector<VL>; using PL=pair<ll,ll>; using VP=vector<PL>; using WG=vector<vector<pair<int,ll>>>; #ifdef LOCAL #include "./debug.hpp" #else #define debug(...) #define print_line #endif /// @brief x^n (mod m) を返す template<typename T=ll> T ModPow(T x, T n, T mod) { T ret=1; if(typeid(T)==typeid(ll)&&mod>INF*2) return ModPow<__int128_t>(x,n,mod); while(n>0) { if(n&1) (ret*=x)%=mod; (x*=x)%=mod; n>>=1; } return ret; } /// @brief x^(-1) (mod m) を返す ll ModInv(ll a, ll m) { ll b=m,u=1,v=0; while(b) { ll t=a/b; a-=t*b; swap(a,b); u-=t*v; swap(u,v); } return (u+m)%m; } /// @brief F_2 上の連立線形方程式 /// @ref https://mathlandscape.com/solution-sp/ /// @ref https://yukicoder.me/submissions/1011997 /// @ref verify:https://yukicoder.me/problems/no/2895 /// @brief 掃き出し法 /// @param a 連立方程式 Ax=b の拡大係数行列 /// @param where ピボットとなる変数を記録するための配列 /// @return A のランク template<int MAX_COL> int RowReduction(vector<bitset<MAX_COL>>& a, int col, vector<int>& where) { int row=a.size(); int rank=0; for(int c=0; c<col-1; c++) { int pivot=rank; while(pivot<row && !a[pivot][c]) pivot++; if(pivot==row) continue; swap(a[pivot],a[rank]); where.push_back(c); for(int r=0; r<row; r++) { if(r!=rank && a[r][c]) a[r]^=a[rank]; } rank++; } return rank; } /// @brief 連立線形方程式 Ax=b を解く /// @param x0 特殊解(b=0 の場合は自明解になる) /// @param ker Ax=0 の解空間の基底 /// @note 一般解は x0 と解空間の基底の任意の線形結合で表される /// @attention A のサイズによっては基底のサイズが巨大になるので注意すること template<int MAX_COL> bool LinearEquation(vector<bitset<MAX_COL>> a, vector<bool> b, int col, vector<bool>& x0, vector<vector<bool>>& ker) { int row=a.size(); assert(b.size()==row); vector<bitset<MAX_COL>> a2(row); for(int i=0; i<row; i++) { a2[i].reset(); for(int j=0; j<col; j++) a2[i][j]=a[i][j]; if(b[i]) a2[i][col]=true; } vector<int> where; int rank=RowReduction<MAX_COL>(a2,col+1,where); for(int r=rank; r<row; r++) if(a2[r][col]) return false; x0=vector<bool>(col,false); for(int i=0; i<rank; i++) x0[where[i]]=a2[i][col]; int r=0; for(int c=0; c<col; c++) { if(r<rank && c==where[r]) { r++; continue; } vector<bool> x(col); x[c]=true; for(int r2=0; r2<r; r2++) x[where[r2]]=a2[r2][c]; ker.push_back(x); } return true; } //---------------------------------------------------------- void solve() { ll N,M,K; cin>>N>>M>>K; const int MAX_COL=2500; vector<bitset<MAX_COL>> A(M); vector<bool> B(M); REP(i,M) { string S; cin>>S; REP(j,MAX_COL-1) A[i][j]=false; REP(j,N) if(S[j]=='1') A[i][j]=true; } vector<bool> x0; vector<vector<bool>> ker; bool res=LinearEquation<MAX_COL>(A,B,N,x0,ker); debug(x0); debug(ker); cout<<ModPow<ll>(2,ker.size(),K)<<endl; } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); cout<<fixed<<setprecision(15); int T=1; //cin>>T; while(T--) solve(); }