public void Ntt_Convolution_Many() { var a = Enumerable.Range(3, 1 << 16).Select(x => (long)x).ToArray(); var b = Enumerable.Range(7, 1 << 16).Select(x => (long)x).ToArray(); Ntt.Convolution(a, b); }
public void Convolution() { var a = new long[] { 1, 2, 3, 4 }; var b = new long[] { 5, 6, 7, 8, 9 }; var expected = new long[] { 5, 16, 34, 60, 70, 70, 59, 36 }; CollectionAssert.AreEqual(expected, Dft.Convolution(a, b)); CollectionAssert.AreEqual(expected, Dft0.Convolution(a, b)); CollectionAssert.AreEqual(expected, Ntt.Convolution(a, b)); CollectionAssert.AreEqual(expected, Ntt0.Convolution(a, b)); }
public void Ntt_Fft_Many() { var n = 1 << 16; var a = Enumerable.Range(3, n).Select(x => (long)x).ToArray(); var ntt = new Ntt(n); var t = ntt.Fft(a); var r = ntt.Fft(t, true); CollectionAssert.AreEqual(a, r); }
// 長さは n 以下で OK。 public static long[] Convolution(long[] a, long[] b) { var ntt = new Ntt(a.Length + b.Length - 1); var fa = ntt.Fft(a); var fb = ntt.Fft(b); for (int i = 0; i < ntt.n; ++i) { fa[i] = fa[i] * fb[i] % p; } return(ntt.Fft(fa, true)); }
static void Main() { var(n, k) = Read2(); var a = ReadL(); var p2 = new long[k + 1]; var f = new long[k + 1]; var f_ = new long[k + 1]; p2[0] = f[0] = f_[0] = 1; for (int x = 1; x <= k; x++) { p2[x] = p2[x - 1] * 2 % M; f[x] = f[x - 1] * x % M; f_[x] = f_[x - 1] * MInv(x) % M; } var pa = Array.ConvertAll(a, _ => 1L); var s1 = new long[k + 1]; var s2 = new long[k + 1]; s1[0] = n; for (int x = 1; x <= k; x++) { var sum = 0L; for (int i = 0; i < n; i++) { sum += pa[i] = pa[i] * a[i] % M; } sum %= M; s1[x] = sum * f_[x] % M; s2[x] = sum * p2[x] % M; } var conv = Ntt.Convolution(s1, s1); var half = MInv(2); for (int x = 1; x <= k; x++) { Console.WriteLine(MInt((f[x] * conv[x] % M - s2[x]) * half)); } }
public void Ntt_Fft() { var n = 1 << 4; var a = Enumerable.Range(3, n).Select(x => (long)x).ToArray(); var t0 = Ntt0.Naive(a); var r0 = Ntt0.Naive(t0, true); var t1 = Ntt0.Fft(a); var r1 = Ntt0.Fft(t1, true); var ntt = new Ntt(n); var t2 = ntt.Fft(a); var r2 = ntt.Fft(t2, true); CollectionAssert.AreEqual(t0, t1); CollectionAssert.AreEqual(t0, t2); CollectionAssert.AreEqual(a, r0); CollectionAssert.AreEqual(a, r1); CollectionAssert.AreEqual(a, r2); }