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