@@ -20,3 +20,48 @@ std::vector<T> interpolation(const T x[], const T y[], int n){
20
20
}
21
21
return ret;
22
22
}
23
+
24
+ // f(x) is degree m - 1, given f(0), f(1), ..., f(m - 1),
25
+ // return f(n) in linear time
26
+ int64 evaluate (const std::vector<int64> &f, int64 n, int64 mod) {
27
+ int64 m = f.size (), nn = n % mod;
28
+ if (n < m) return f[n];
29
+ std::vector<int64> inv (m + 1 ), fact (m + 1 ), ifact (m + 1 );
30
+ inv[1 ] = fact[0 ] = ifact[0 ] = fact[1 ] = ifact[1 ] = 1 ;
31
+ for (int i = 2 ; i <= m; ++i) {
32
+ inv[i] = int64 (mod - mod / i) * inv[mod % i] % mod;
33
+ fact[i] = (int64)i * fact[i - 1 ] % mod;
34
+ ifact[i] = (int64)inv[i] * ifact[i - 1 ] % mod;
35
+ }
36
+ int64 ret = 0 , v = 1 ;
37
+ std::vector<int64> s (m + 1 );
38
+ s[m] = 1 ;
39
+ for (int i = m - 1 ; i >= 0 ; --i) {
40
+ v = (int64)v * (nn - i + mod) % mod;
41
+ s[i] = (int64)s[i + 1 ] * (nn - i + mod) % mod;
42
+ if (i == nn) s[i] = 1 ;
43
+ }
44
+ v = pow_mod (v, mod - 2 , mod);
45
+ for (int i = 0 ; i < m; ++i) {
46
+ int64 inv2 = (int64)v * s[i + 1 ] % mod;
47
+ v = (int64)v * (nn - i + mod) % mod;
48
+ int64 mul = (int64)ifact[i] * ifact[m - 1 - i] % mod * inv2 % mod;
49
+ if ((m - 1 - i) & 1 ) mul = mod - mul;
50
+ if (i != nn) {
51
+ ret += f[i] * mul % mod;
52
+ }
53
+ if (ret >= mod) ret -= mod;
54
+ }
55
+ for (int i = 0 ; i < m; ++i) {
56
+ ret = (int64)ret * (nn - i + mod) % mod;
57
+ }
58
+ if (nn <= m - 1 ) {
59
+ int64 extra = f[nn] * ifact[nn] % mod * ifact[m - 1 - nn] % mod;
60
+ if ((m - 1 - nn) & 1 ) extra = mod - extra;
61
+ for (int i = 0 ; i < m; ++i) {
62
+ if (i != nn) extra = extra * (nn - i + mod) % mod;
63
+ }
64
+ ret = (ret + extra) % mod;
65
+ }
66
+ return ret;
67
+ }
0 commit comments