結果
| 問題 |
No.2048 L(I+D)S
|
| コンテスト | |
| ユーザー |
qwewe
|
| 提出日時 | 2025-05-14 13:11:33 |
| 言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
AC
|
| 実行時間 | 7 ms / 2,000 ms |
| コード長 | 6,236 bytes |
| コンパイル時間 | 728 ms |
| コンパイル使用メモリ | 70,632 KB |
| 実行使用メモリ | 6,272 KB |
| 最終ジャッジ日時 | 2025-05-14 13:13:16 |
| 合計ジャッジ時間 | 1,562 ms |
|
ジャッジサーバーID (参考情報) |
judge1 / judge4 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 3 |
| other | AC * 16 |
ソースコード
#include <iostream>
#include <vector>
// Define the modulus
const long long MOD = 998244353;
// Function for modular exponentiation (calculates base^exp % MOD)
// Used for calculating modular inverse via Fermat's Little Theorem
long long power(long long base, long long exp) {
long long res = 1;
base %= MOD;
while (exp > 0) {
if (exp % 2 == 1) res = (res * base) % MOD;
base = (base * base) % MOD;
exp /= 2;
}
return res;
}
// Function to calculate modular inverse using Fermat's Little Theorem
// This works because MOD = 998244353 is a prime number.
// The inverse of n modulo MOD is n^(MOD-2) % MOD.
long long modInverse(long long n) {
// The constraints of the problem ensure n will be positive and less than MOD.
// Thus n % MOD != 0. No need to handle n=0 case.
return power(n, MOD - 2);
}
// Maximum value of N based on problem constraints
const int MAXN = 100005;
// Arrays to store precomputed values:
// fact[i] = i! % MOD
// invFact[i] = (i!)^(-1) % MOD, modular inverse of i!
// inv[i] = i^(-1) % MOD, modular inverse of i
long long fact[MAXN];
long long invFact[MAXN];
long long inv[MAXN];
// Function to precompute factorials, inverse factorials, and modular inverses up to N
void precompute(int N) {
// Base cases for factorial and inverse factorial
fact[0] = 1;
invFact[0] = 1;
// Handle N >= 1 cases if needed
if (N >= 1) {
fact[1] = 1;
invFact[1] = 1;
inv[1] = 1; // Modular inverse of 1 is 1
}
// Calculate factorials, modular inverses, and inverse factorials iteratively up to N
for (int i = 2; i <= N; ++i) {
// Calculate factorial: fact[i] = (i-1)! * i % MOD
fact[i] = (fact[i - 1] * i) % MOD;
// Calculate modular inverse using the O(N) formula:
// inv[i] = MOD - (MOD / i) * inv[MOD % i] % MOD
// This formula is derived from the extended Euclidean algorithm relation:
// MOD = q*i + r => q*i + r = 0 (mod MOD) => r = -q*i (mod MOD)
// => r^{-1} = (-q*i)^{-1} (mod MOD) => r^{-1} = -(q^{-1}) * i^{-1} (mod MOD) -- No this is wrong derivation
// Better explanation: q*i + r = 0 (mod MOD) => r = -q*i (mod MOD)
// 1 = r * inv[r] (mod MOD) => 1 = (-q*i) * inv[r] (mod MOD)
// Multiply by inv[i]: inv[i] = (-q*i) * inv[r] * inv[i] (mod MOD)
// inv[i] = -q * inv[r] (mod MOD)
// inv[i] = -(MOD / i) * inv[MOD % i] (mod MOD)
// To ensure positive result: inv[i] = MOD - (MOD / i) * inv[MOD % i] % MOD
inv[i] = MOD - (MOD / i) * inv[MOD % i] % MOD;
// Calculate inverse factorials using the relation:
// (i!)^{-1} = ((i-1)!)^{-1} * i^{-1} % MOD
invFact[i] = (invFact[i - 1] * inv[i]) % MOD;
}
}
int main() {
// Use fast I/O operations
std::ios_base::sync_with_stdio(false);
std::cin.tie(NULL);
int N; // Input integer N
std::cin >> N;
// If N <= 3, the condition LIS + LDS = N cannot be satisfied by any permutation.
// The number of rows k must satisfy 2 <= k <= N-2. This range is empty if N-2 < 2, i.e., N < 4.
if (N <= 3) {
std::cout << 0 << std::endl;
return 0;
}
// Precompute factorials, inverse factorials, and modular inverses up to N
// The maximum index needed is N for fact, invFact, and N-1 for inv.
precompute(N);
long long total_count = 0; // Initialize the total count of permutations satisfying the condition
// Iterate through possible values of k (length of the Longest Decreasing Subsequence)
// The Robinson-Schensted correspondence relates LIS/LDS lengths to Young Tableau shapes.
// LIS = lambda_1 (length of first row), LDS = k (number of rows)
// The condition LIS + LDS = N translates to lambda_1 + k = N.
// Analysis shows the shapes must be of the form lambda = (N-k, 2, 1^{k-2})
// The constraints require 2 <= k <= N-2.
for (int k = 2; k <= N - 2; ++k) {
// Calculate f^lambda, the number of Standard Young Tableaux (SYT) for the shape lambda.
// The hook length formula gives f^lambda = N! / H, where H is the product of hook lengths.
// The product of hook lengths H for shape (N-k, 2, 1^{k-2}) is:
// H = (N-1) * (N-k) * (N-k-2)! * k * (k-2)!
// Prepare indices and values needed for calculation
long long N_minus_1 = N - 1;
long long N_minus_k = N - k;
long long k_val = k;
int N_minus_k_minus_2 = N - k - 2; // Index for invFact array
int k_minus_2 = k - 2; // Index for invFact array
// Ensure indices are valid (non-negative).
// Given k in [2, N-2], we have k >= 2 => k-2 >= 0.
// Also N-k >= 2 => N-k-2 >= 0. The indices are always valid.
// Calculate the modular inverse of H.
// H^{-1} = (N-1)^{-1} * (N-k)^{-1} * ((N-k-2)! )^{-1} * k^{-1} * ((k-2)! )^{-1} (mod MOD)
// Fetch precomputed modular inverses and inverse factorials
long long inv_N_minus_1 = inv[N_minus_1];
long long inv_N_minus_k = inv[N_minus_k];
long long inv_k = inv[k_val];
long long invFact_N_minus_k_minus_2 = invFact[N_minus_k_minus_2];
long long invFact_k_minus_2 = invFact[k_minus_2];
// Compute f^lambda = (N! * H^{-1}) % MOD
long long f_lambda = fact[N]; // Start with N!
f_lambda = (f_lambda * inv_N_minus_1) % MOD; // Multiply by (N-1)^{-1}
f_lambda = (f_lambda * inv_N_minus_k) % MOD; // Multiply by (N-k)^{-1}
f_lambda = (f_lambda * invFact_N_minus_k_minus_2) % MOD; // Multiply by ((N-k-2)! )^{-1}
f_lambda = (f_lambda * inv_k) % MOD; // Multiply by k^{-1}
f_lambda = (f_lambda * invFact_k_minus_2) % MOD; // Multiply by ((k-2)! )^{-1}
// The number of permutations corresponding to shape lambda is (f^lambda)^2.
long long f_lambda_sq = (f_lambda * f_lambda) % MOD; // Calculate (f^lambda)^2 mod MOD
// Add this count to the total sum
total_count = (total_count + f_lambda_sq) % MOD;
}
// Output the final computed count modulo MOD
std::cout << total_count << std::endl;
return 0;
}
qwewe