結果
問題 | No.856 増える演算 |
ユーザー |
👑 |
提出日時 | 2019-07-26 22:50:33 |
言語 | D (dmd 2.109.1) |
結果 |
AC
|
実行時間 | 526 ms / 3,153 ms |
コード長 | 9,447 bytes |
コンパイル時間 | 1,540 ms |
コンパイル使用メモリ | 159,356 KB |
実行使用メモリ | 32,736 KB |
最終ジャッジ日時 | 2024-06-22 02:07:25 |
合計ジャッジ時間 | 32,196 ms |
ジャッジサーバーID (参考情報) |
judge4 / judge2 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
sample | AC * 3 |
other | AC * 80 |
コンパイルメッセージ
Main.d(332): Deprecation: function `std.math.exponential.log` is deprecated - `std.math.exponential.log` called with argument types `(long)` matches both `log(real)`, `log(double)`, and `log(float)`. Cast argument to floating point type instead. Main.d(332): Deprecation: function `std.math.exponential.log` is deprecated - `std.math.exponential.log` called with argument types `(long)` matches both `log(real)`, `log(double)`, and `log(float)`. Cast argument to floating point type instead.
ソースコード
import std.conv, std.functional, std.range, std.stdio, std.string;import std.algorithm, std.array, std.bigint, std.complex, std.container, std.math, std.numeric, std.regex, std.typecons;import core.bitop;class EOFException : Throwable { this() { super("EOF"); } }string[] tokens;string readToken() { for (; tokens.empty; ) { if (stdin.eof) { throw new EOFException; } tokens = readln.split; } auto token = tokens.front; tokens.popFront; return token; }int readInt() { return readToken.to!int; }long readLong() { return readToken.to!long; }real readReal() { return readToken.to!real; }bool chmin(T)(ref T t, in T f) { if (t > f) { t = f; return true; } else { return false; } }bool chmax(T)(ref T t, in T f) { if (t < f) { t = f; return true; } else { return false; } }int binarySearch(alias pred, T)(in T[] as) { int lo = -1, hi = cast(int)(as.length); for (; lo + 1 < hi; ) { const mid = (lo + hi) >> 1;(unaryFun!pred(as[mid]) ? hi : lo) = mid; } return hi; }int lowerBound(T)(in T[] as, T val) { return as.binarySearch!(a => (a >= val)); }int upperBound(T)(in T[] as, T val) { return as.binarySearch!(a => (a > val)); }struct ModInt(long M) {long x;this(in ModInt a) { x = a.x; }this(in long a) { x = a % M; if (x < 0) x += M; }ref ModInt opAssign(in long a) { return this = ModInt(a); }ref ModInt opOpAssign(string op)(in ModInt a) {static if (op == "+") { x += a.x; if (x >= M) x -= M; }else static if (op == "-") { x -= a.x; if (x < 0) x += M; }else static if (op == "*") { x *= a.x; x %= M; }else static assert(false);return this;}ref ModInt opOpAssign(string op)(in long a) { return mixin("this " ~ op ~ "= ModInt(a)"); }ModInt opUnary(string op)() const if (op == "-") { return ModInt(-x); }ModInt opBinary(string op, T)(in T a) const { return mixin("ModInt(this) " ~ op ~ "= a"); }ModInt opBinaryRight(string op)(in long a) const { return mixin("ModInt(a) " ~ op ~ "= this"); }string toString() const { return x.to!string; }}// a^-1 (mod 2^64)long modInv(long a)in {assert(a & 1, "modInv: a must be odd");}do {long b = ((a << 1) + a) ^ 2;b *= 2 - a * b;b *= 2 - a * b;b *= 2 - a * b;b *= 2 - a * b;return b;}// a^-1 (mod m)long modInv(long a, long m)in {assert(m > 0, "modInv: m > 0 must hold");}do {long b = m, x = 1, y = 0, t;for (; ; ) {t = a / b;a -= t * b;if (a == 0) {assert(b == 1 || b == -1, "modInv: gcd(a, m) != 1");if (b == -1) {y = -y;}return (y < 0) ? (y + m) : y;}x -= t * y;t = b / a;b -= t * a;if (b == 0) {assert(a == 1 || a == -1, "modInv: gcd(a, m) != 1");if (a == -1) {x = -x;}return (x < 0) ? (x + m) : x;}y -= t * x;}}// 2^-31 a (mod M)long montgomery(long M)(long a) if (1 <= M && M <= 0x7fffffff && (M & 1))in {assert(0 <= a && a < (M << 31), "montgomery: 0 <= a < 2^31 M must hold");}do {enum negInvM = -modInv(M) & 0x7fffffff;const b = (a + ((a * negInvM) & 0x7fffffff) * M) >> 31;return (b >= M) ? (b - M) : b;}// FFT on Z / M Z with Montgomery multiplication (x -> 2^31 x)// G: primitive 2^K-th root of unityclass FFT(long M, int K, long G)if (is(typeof(montgomery!(M)(0))) && K >= 0 && 0 < G && G < M) {import std.algorithm : swap;import core.bitop : bsf;int n, invN;long[] g;this(int n)in {assert(!(n & (n - 1)), "FFT.this: n must be a power of 2");assert(4 <= n && n <= 1 << K, "FFT.this: 4 <= n <= 2^K must hold");}do {this.n = n;this.invN = ((1L << 31) / n) % M;g.length = n + 1;g[0] = (1L << 31) % M;g[1] = (G << 31) % M;foreach (_; 0 .. K - bsf(n)) {g[1] = montgomery!(M)(g[1] * g[1]);}foreach (i; 2 .. n + 1) {g[i] = montgomery!(M)(g[i - 1] * g[1]);}assert(g[0] != g[n >> 1] && g[0] == g[n],"FFT.this: G must be a primitive 2^K-th root of unity");for (int i = 0, j = 0; i < n >> 1; ++i) {if (i < j) {swap(g[i], g[j]);swap(g[n - i], g[n - j]);}for (int m = n >> 1; (m >>= 1) && !((j ^= m) & m); ) {}}}void fftMontgomery(long[] x, bool inv)in {assert(x.length == n, "FFT.fftMontgomery: |x| = n must hold");}do {foreach_reverse (h; 0 .. bsf(n)) {const l = 1 << h;foreach (i; 0 .. n >> 1 >> h) {const gI = g[inv ? (n - i) : i];foreach (j; i << 1 << h .. ((i << 1) + 1) << h) {const t = montgomery!(M)(gI * x[j + l]);if ((x[j + l] = x[j] - t) < 0) {x[j + l] += M;}if ((x[j] += t) >= M) {x[j] -= M;}}}}for (int i = 0, j = 0; i < n; ++i) {if (i < j) {swap(x[i], x[j]);}for (int m = n; (m >>= 1) && !((j ^= m) & m); ) {}}if (inv) {foreach (i; 0 .. n) {x[i] = montgomery!(M)(invN * x[i]);}}}long[] convolution(long[] a, long[] b)in {assert(a.length <= n, "FFT.convolution: |a| <= n must hold");assert(b.length <= n, "FFT.convolution: |b| <= n must hold");}do {auto x = new long[n], y = new long[n];foreach (i; 0 .. a.length) {const t = a[i] % M;x[i] = (((t < 0) ? (t + M) : t) << 31) % M;}foreach (i; 0 .. b.length) {const t = b[i] % M;y[i] = (((t < 0) ? (t + M) : t) << 31) % M;}fftMontgomery(x, false);fftMontgomery(y, false);foreach (i; 0 .. n) {x[i] = montgomery!(M)(x[i] * y[i]);}fftMontgomery(x, true);foreach (i; 0 .. n) {x[i] = montgomery!(M)(x[i]);}return x;}}// P0 P1 P2 > 2^90, P0 + P1 + P2 = 2^32 + 3enum FFT_P0 = 2013265921L; // 2^27 15 + 1enum FFT_P1 = 1811939329L; // 2^26 27 + 1enum FFT_P2 = 469762049L; // 2^26 7 + 1alias FFT0 = FFT!(FFT_P0, 27, 440564289L); // 31^15alias FFT1 = FFT!(FFT_P1, 26, 72705542L); // 13^27alias FFT2 = FFT!(FFT_P2, 26, 2187L); // 3^ 7// Convolution of a and b (indices mod fft0.n)// modify a and b so that 0 <= a[i] < m, 0 <= b[i] < mlong[] convolution(FFT0 fft0, FFT1 fft1, FFT2 fft2, long[] a, long[] b, long m)in {assert(fft0.n == fft1.n && fft0.n == fft2.n, "convolution: fft0.n = fft1.n = fft2.n must hold");assert(1 <= m && m <= 0x7fffffff, "convolution: 1 <= m < 2^31 must hold");}do {enum FFT_INV01 = modInv(FFT_P0, FFT_P1);enum FFT_INV012 = modInv(FFT_P0 * FFT_P1, FFT_P2);foreach (i; 0 .. a.length) {if ((a[i] %= m) < 0) {a[i] += m;}}foreach (i; 0 .. b.length) {if ((b[i] %= m) < 0) {b[i] += m;}}const x0 = fft0.convolution(a, b);const x1 = fft1.convolution(a, b);const x2 = fft2.convolution(a, b);auto x = new long[fft0.n];foreach (i; 0 .. fft0.n) {auto y0 = x0[i] % FFT_P0;auto y1 = (FFT_INV01 * (x1[i] - y0)) % FFT_P1;if (y1 < 0) {y1 += FFT_P1;}auto y2 = (FFT_INV012 * ((x2[i] - y0 - FFT_P0 * y1) % FFT_P2)) % FFT_P2;if (y2 < 0) {y2 += FFT_P2;}x[i] = (y0 + FFT_P0 * y1 + ((FFT_P0 * FFT_P1) % m) * y2) % m;}return x;}enum long MO = 1000000007;alias Mint = ModInt!MO;Mint power(Mint a, long e) {Mint x = a, y = 1;for (; e; e >>= 1) {if (e & 1) y *= x;x *= x;}return y;}enum L = 2^^18;int N;long[] A;void main() {auto fft = new Fft(L);auto fft0 = new FFT0(L);auto fft1 = new FFT1(L);auto fft2 = new FFT2(L);try {for (; ; ) {N = readInt();A = new long[N];foreach (i; 0 .. N) {A[i] = readInt();}// auto f = new real[L];// f[] = 0.0;// foreach (i; 0 .. N) {// f[cast(int)(A[i])] += 1;// }// auto ff = fft.fft!real(f);// foreach (l; 0 .. L) {// ff[l] = ff[l] * ff[l];// }// auto g = fft.inverseFft!real(ff);// pragma(msg,typeof(g));// foreach (i; 0 .. N) {// g[cast(int)(2 * A[i])] -= 1.0;// }// auto cnt = new long[L];// foreach (l; 0 .. L) {// cnt[l] = cast(long)(round(g[l].re / 2.0));// }// debug {// writeln("cnt = ", cnt[0 .. 20]);// }auto f = new long[L];foreach (i; 0 .. N) {++f[cast(int)(A[i])];}auto g = convolution(fft0, fft1, fft2, f, f, 2 * (MO - 1));foreach (i; 0 .. N) {const l = cast(int)(2 * A[i]);--g[l];if (g[l] < 0) {g[l] += 2 * (MO - 1);}}foreach (l; 0 .. L) {assert(g[l] % 2 == 0);g[l] /= 2;}debug {writeln("g = ", g[0 .. 20]);}Mint ans = 1;foreach (l; 0 .. L) {ans *= power(Mint(l), g[l]);}long ASum;foreach_reverse (i; 0 .. N) {ans *= power(Mint(A[i]), ASum);ASum += A[i];}long AMin = long.max;auto opt = tuple(real.infinity, 0L, 0L);foreach_reverse (i; 0 .. N) {if (i < N - 1) {chmin(opt, tuple(log(A[i] + AMin) + log(A[i]) * AMin, A[i], AMin));}chmin(AMin, A[i]);}debug {writeln("opt = ", opt);}Mint dnm = (opt[1] + opt[2]) * power(Mint(opt[1]), opt[2]);ans *= modInv(dnm.x, MO);writeln(ans);}} catch (EOFException e) {}}