大概就是有 $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;
    }
}
View Code

相关文章: