結果
問題 |
No.3123 Inversion
|
ユーザー |
|
提出日時 | 2025-04-19 16:12:36 |
言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
結果 |
WA
|
実行時間 | - |
コード長 | 3,858 bytes |
コンパイル時間 | 2,382 ms |
コンパイル使用メモリ | 200,844 KB |
実行使用メモリ | 144,036 KB |
最終ジャッジ日時 | 2025-04-19 16:13:16 |
合計ジャッジ時間 | 39,378 ms |
ジャッジサーバーID (参考情報) |
judge3 / judge1 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
sample | WA * 1 |
other | AC * 1 WA * 20 |
ソースコード
#include <bits/stdc++.h> using namespace std; using int64 = long long; // fast modular arithmetic static int add(int a, int b, int M){ a+=b; if(a>=M) a-=M; return a; } static int sub(int a, int b, int M){ a-=b; if(a<0) a+=M; return a; } static int64 mul(int64 a, int64 b, int M){ return (a*b) % M; } static int64 modpow(int64 x, int64 e, int M) { int64 r=1%M, y=x%M; while(e){ if(e&1) r=(r*y)%M; y=(y*y)%M; e>>=1; } return r; } int main(){ ios::sync_with_stdio(false); cin.tie(nullptr); int T, M; cin >> T >> M; vector<int> Ns(T); int Nmax = 0; for(int i=0;i<T;i++){ cin >> Ns[i]; Nmax = max(Nmax, Ns[i]); } // Precompute factorials and inv‐factorials mod M: vector<int> fac(Nmax+1, 1); for(int i=1;i<=Nmax;i++) fac[i] = int(mul(fac[i-1], i, M)); // Precompute involutions A[n]: A[0]=A[1]=1; A[n]=A[n-1] + (n-1)*A[n-2] vector<int> A(Nmax+1, 0); A[0] = 1 % M; if(Nmax >= 1) A[1] = 1 % M; for(int n=2;n<=Nmax;n++){ A[n] = add( A[n-1], int(mul(n-1, A[n-2], M)), M ); } // Precompute B[n] = floor(n/2) even? B[n] = (t)! / (t/2)! else 0 vector<int> B(Nmax+1, 0); // We need factorials up to Nmax/2 and inverse factorials if M not prime // but here we only divide factorials by factorial (t/2)!; M may be non‐prime so we do it by // building up via B[n] = B[n-2] * (n/2) * (n/2 - 1) ... accordingly. B[0] = 1 % M; // by convention for(int n=1;n<=Nmax;n++){ int t = n/2; if(t%2==0){ // B[n] = fac[t] * inv( fac[t/2] ) mod M // we'll just do fac[t] * modinv(fac[t/2]) // since M up to 1e9 (not prime), we can precompute invs by extended gcd if needed. // For simplicity, we'll precompute all inverses by egcd: static vector<int64> invFac; if(invFac.empty()){ invFac.resize(Nmax+1); // compute invFac[i] = inv( fac[i] ) mod M via extended‐gcd auto exgcd = [&](auto self, int64 a, int64 b, int64 &x, int64 &y)->int64 { if(!b){ x=1; y=0; return a; } int64 x1,y1; int64 g = self(self, b, a%b, x1, y1); x = y1; y = x1 - (a/b)*y1; return g; }; for(int i=0;i<=Nmax;i++){ int64 x,y; int64 g = exgcd(exgcd, fac[i], M, x, y); // Since fac[i] and M may not be coprime, but in every test // fac[t/2] will be invertible for our ranges (by constraints), // we assume g==1 here. x %= M; if(x<0) x += M; invFac[i] = x; } } B[n] = int( mul( fac[t], invFac[t/2], M ) ); } else { B[n] = 0; } } // Precompute C[n] = m1! * 2^{m2} * m2! mod M vector<int> C(Nmax+1, 0), pow2(Nmax+1,1); for(int i=1;i<=Nmax;i++) pow2[i] = add(pow2[i-1], pow2[i-1], M); for(int n=0;n<=Nmax;n++){ int m1 = n & 1; int m2 = n >> 1; int64 v = fac[m1]; v = (v * pow2[m2]) % M; v = (v * fac[m2]) % M; C[n] = int(v); } // Now answer each query: // S(N) = 8*N! - 4*A[N] - 2*B[N] - 2*C[N] (for N>=2), S(1)=1 for(int n: Ns){ if(n==1){ cout << 1 << "\n"; } else { int64 res = 0; // 8*N! res = (res + 8LL * fac[n]) % M; // -4*A[n] res = (res - 4LL * A[n]) % M; // -2*B[n] res = (res - 2LL * B[n]) % M; // -2*C[n] res = (res - 2LL * C[n]) % M; if(res<0) res += M; cout << res << "\n"; } } return 0; }