大概就是有 $n$ 对点 $(x_i,y_i)$ 让你构造一个 $n-1$ 次多项式函数过这些点,求这个多项式函数在 $k$ 处的点值
这是一个构造题,我们构造一个函数
$\sum\limits_{i=0}^{n-1} y_i \times \prod\limits_{j=0}^{n-1} \frac{x-x_j}{x_i-x_j}$
然后就没有然后了...
展开求这个多项式函数的每一项是 $O(n^3)$ 的,如果要求点值的话就把 $k$ 代进去就行了
例题比如
bzoj2655 calc
一道很缺德的题
一个序列a1,...,an是合法的,当且仅当:
长度为给定的n。
a1,...,an都是[1,A]中的整数。
a1,...,an互不相等。
一个序列的值定义为它里面所有数的乘积,即a1a2...an。
求所有不同合法序列的值的和。
两个序列不同当且仅当他们任意一位不一样。
输出答案对一个数mod取余的结果。
$n \leq 500,A \leq 1e9,mod是质数$
sol:
首先你可以想到一个 $O(n^2)$ 的 dp:
$f(i,j)$ 表示值域为 $i$,有 $j$ 个数的不同合法序列值的和
$f(0,0) = 1; f(i,j) = f(i-1,j-1)*i*j+f(i-1,j)$
然后发现这是一个 $2n$ 次多项式...(打表找规律
插值即可
#include <bits/stdc++.h> #define int long long #define LL long long #define rep(i, s, t) for (register int i = (s), i##end = (t); i <= i##end; ++i) #define dwn(i, s, t) for (register int i = (s), i##end = (t); i >= i##end; --i) using namespace std; inline int read() { int x = 0, f = 1; char ch; for (ch = getchar(); !isdigit(ch); ch = getchar()) if (ch == '-') f = -f; for (; isdigit(ch); ch = getchar()) x = 10 * x + ch - '0'; return x * f; } int A, n, mod; int f[5100][5100]; inline int ksm(int x, int t) { int res = 1; for(; t; x = 1LL * x * x % mod, t >>= 1) if(t & 1) res = 1LL * x * res % mod; return res; } int nodval[5100]; signed main() { A = read(), n = read(), mod = read(); f[0][0] = 1; rep(i, 1, n+n) { f[i][0] = f[i - 1][0]; rep(j, 1, n) f[i][j] = ((((1LL * f[i-1][j-1] * i) % mod) * (LL)j) % mod + f[i-1][j]) % mod; } if(A <= n+n) cout << f[A][n] << endl; else { int ans = 0; rep(i, 0, 2*n) { int t1 = 1, t2 = 1; rep(j, 0, 2*n) { if(i == j) continue; t1 = 1LL * (A - j) * t1 % mod; t2 = 1LL * (i - j) * t2 % mod; } ans = (ans + (1LL * (f[i][n] * t1) % mod * ksm(t2, mod-2)) % mod) % mod; } cout << (ans%mod + mod)%mod << endl; } }