結果
| 問題 |
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;
}