結果
| 問題 |
No.3178 free sort
|
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2025-06-13 22:38:06 |
| 言語 | D (dmd 2.109.1) |
| 結果 |
AC
|
| 実行時間 | 18 ms / 2,000 ms |
| コード長 | 4,148 bytes |
| コンパイル時間 | 4,029 ms |
| コンパイル使用メモリ | 202,236 KB |
| 実行使用メモリ | 11,096 KB |
| 最終ジャッジ日時 | 2025-06-13 22:38:15 |
| 合計ジャッジ時間 | 6,146 ms |
|
ジャッジサーバーID (参考情報) |
judge1 / judge5 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 5 |
| other | AC * 40 |
ソースコード
import std;
void main () {
auto S = readln.chomp.map!(a => a - '0').array;
const int N = S.length.to!int;
const long MOD = 998244353;
alias m = PrimeModuloFactorial!MOD;
m.build(N + 100);
auto count = new int[](10);
foreach (c; S) {
count[c]++;
}
long ans = 0;
foreach (i; 1 .. 10) {
if (count[i] == 0) {
continue;
}
count[i]--;
long add = m.factorial(N - 1);
foreach (j; 0 .. 10) {
add *= m.factorial_inv(count[j]);
add %= MOD;
}
count[i]++;
ans += add;
ans %= MOD;
}
writeln(ans);
}
// check mod_pow
static assert(__traits(compiles, mod_pow(2, 10, 998244353)));
long mod_inv (const long x, const long MOD)
in {
import std.format : format;
assert(1 <= MOD, format("MOD must satisfy 1 <= MOD. Now MOD = %s.", MOD));
assert(MOD <= int.max, format("MOD must satisfy MOD*MOD <= long.max. Now MOD = %s.", MOD));
}
do {
return mod_pow(x, MOD-2, MOD);
}
long mod_pow (long a, long x, const long MOD)
in {
assert(0 <= x, "x must satisfy 0 <= x");
assert(1 <= MOD, "MOD must satisfy 1 <= MOD");
assert(MOD <= int.max, "MOD must satisfy MOD*MOD <= long.max");
}
do {
// normalize
a %= MOD; a += MOD; a %= MOD;
long res = 1L;
long base = a;
while (0 < x) {
if (0 < (x&1)) (res *= base) %= MOD;
(base *= base) %= MOD;
x >>= 1;
}
return res % MOD;
}
// check mod_inv
static assert(__traits(compiles, mod_inv(998244353, 1_000_000_007)));
class PrimeModuloFactorial (ulong M)
{
/// methods:
/// - void build (ulong N_)
/// - long binom (ulong n_, ulong k_)
/// - long factorial (ulong x_)
/// - long factorial_inv (ulong x_)
import std.conv : to;
import std.format : format;
// varidate
static assert(1 <= M && M < int.max, format("PrimeModuloFactorial: M = %s is out of range. M must be in range of [1, %s].", M, int.max));
private static bool internal_is_prime (int x) {
if (x <= 1) return false;
foreach (i; 2..x + 1) {
if (x < 1L * i * i) break;
if (x % i == 0) return false;
}
return true;
}
static assert(internal_is_prime(M.to!int), format("PrimeModuloFactorial: M = %s is not prime number.", M));
private:
static long[] fact, fact_inv;
static int N = 0;
static long MOD = M;
public:
@disable this () {}
static void build (ulong N_)
in {
assert(0 <= N_ && N_ <= 10^^8, format("N = %s does not satisfy constraints. N must be in range of [0, 10^8].", N_));
}
do {
if (N_ <= N) { N = N_.to!int; return; }
N = N_.to!int;
fact.length = fact_inv.length = N + 1;
fact[0] = 1;
for (int i = 1; i <= N; i++) fact[i] = i * fact[i - 1] % MOD;
fact_inv[N] = mod_inv(fact[N], MOD);
for (int i = N; 0 < i; i--) fact_inv[i - 1] = i * fact_inv[i] % MOD;
}
static long binom (ulong n_, ulong k_)
in {
assert((n_ < k_
|| (n_ <= N && k_ <= N)),
format("Out of range of pre-calculation. MAX = %s, n = %s, k = %s.", N, n_, k_),
);
}
do {
int n = n_.to!int;
int k = k_.to!int;
if (n < k) return 0;
long res = fact[n] * fact_inv[k] % MOD;
return res * fact_inv[n - k] % MOD;
}
static long factorial (ulong x_)
in {
assert(x_ <= N,
format("Out of range of pre-calculation. MAX = %s, x = %s.", N, x_),
);
}
do {
int x = x_.to!int;
return fact[x];
}
static long factorial_inv (ulong x_)
in {
assert(x_ <= N,
format("Out of range of pre-calculation. MAX = %s, x = %s.", N, x_)
);
}
do {
int x = x_.to!int;
return fact_inv[x];
}
}