题面
解法
可以发现,题目可以转化成求若干个形如\(\sum_{i=1}^ni^k\)的东西
这个东西可以拉格朗日插值
大概讲一下拉格朗日插值是个什么东西:
显然,\(\sum_{i=1}^ni^k\)可以用一个\(k+1\)次多项式表示出来
那么,将\(x_i=1,2,…k+1\)代入,求得\(y_i\)
表达式即可表示为$\(y=\sum_{i=1}^{k+1}y_i\frac{(x-x_1)(x-x_2)…(x-x_{k+1})}{(x_i-x_1)(x_i-x_2)…(x_i-x_{k+1})}\)
另外,每一项分子分母上都不会出现\(x-x_i\)和\(x_i-x_i\)的东西
将\(x_i\)代入,显然是正确的
时间复杂度:\(O(TM^3)\)
代码
#include <bits/stdc++.h>
#define Mod 1000000007
#define LL long long
#define N 100
using namespace std;
template <typename node> void read(node &x) {
x = 0; int f = 1; char c = getchar();
while (!isdigit(c)) {if (c == '-') f = -1; c = getchar();}
while (isdigit(c)) x = x * 10 + c - '0', c = getchar(); x *= f;
}
int x[N], y[N];
LL a[N];
int Pow(int x, int y) {
int ret = 1;
while (y) {
if (y & 1) ret = 1ll * ret * x % Mod;
y >>= 1, x = 1ll * x * x % Mod;
}
return ret;
}
int solve(int n, int k) {
int ret = 0;
for (int i = 1; i <= k + 2; i++) {
int tx = y[i], ty = 1;
for (int j = 1; j <= k + 2; j++) {
if (i == j) continue;
tx = 1ll * tx * (n - x[j]) % Mod;
ty = 1ll * ty * (x[i] - x[j]) % Mod;
}
tx = 1ll * tx * Pow(ty, Mod - 2) % Mod;
ret = ((LL)ret + tx + Mod) % Mod;
}
return ret;
}
int main() {
int T; read(T);
while (T--) {
LL n, m; read(n), read(m); a[0] = 0;
for (int i = 1; i <= m; i++) read(a[i]);
int k = m + 1; sort(a + 1, a + m + 1);
for (int i = 1; i <= k + 2; i++)
x[i] = i, y[i] = ((LL)y[i - 1] + Pow(i, k)) % Mod;
int ans = 0;
for (int i = 0; i <= m; i++) {
LL l = n - a[i];
ans = ((LL)ans + solve(l, k)) % Mod;
for (int j = i + 1; j <= m; j++)
ans = (ans - Pow(a[j] - a[i], k) + Mod) % Mod;
}
cout << ans << "\n";
}
return 0;
}