Description

给定 $n,x$ 和 $m$ 次多项式 $f$ (给出 $0 \cdots m$ 的点值) ,求

Tutorial

设 $f$ 转化为下降幂多项式时的系数为 $b_0 \cdots b_m$

使用类似于联合省选组合数问题的技巧,我们有

接下来考虑如何求 $b_i$,当然可以先插值再转为下降幂,但出题人给点值 显然 不是用来恶心人的,考虑直接通过点值求 $b_i$

因为

设 $f$ 的普通幂系数为 $a_0 \cdots a_m$,我们有

然后考虑一个恒等式

这很容易用组合意义证明

二项式反演得到

我怎么把第二类斯特林数·行的式子推了一遍

带入 $(2)$,得到

这十分的卷积,显然可以 $O(m \log m)$ 计算

然后把算出来的$b_i$ 带回 $(1)$ 就好了

UPD0

突然发现我好傻逼,转下降幂完全不用那么烦

直接二项式反演

我之前在干什么。。。

Code

一个 ntt 调了两个小时的我是屑

// at https://gitee.com/coderoj/code/blob/master/creats/Scanner.h
#include "/home/jack/code/creats/Scanner.h"
#include <bits/stdc++.h>
constexpr int N = 65536;
constexpr int MOD = 998244353;
int n, m, x;
int a[N], b[N];
int power(int a, int b) {
 int r = 1;
 for (;b;b>>=1) {
   if (b & 1) { r = 1ll * r * a % MOD; }
   a = 1ll * a * a % MOD; }
 return r; }
inline void checkAdd(int& a) { a += a < 0 ? MOD : 0; }
inline void checkSub(int& a) { a -= a >= MOD ? MOD : 0; }
namespace polys {
void dft(int *const a, int n) {
 int len = (1 << n);
 static int rev[N], w[N], last_n = -1;
 if (last_n != n) { last_n = n;
   rev[0] = 0;
   for (int i=1; i<len; ++i) {
     rev[i] = (rev[i>>1] >> 1) | ((i&1) << (n-1)); }
   for (int i=0; i<n; ++i) {
     int p = 1 << i; int pw = power(3, (MOD-1) / p / 2); w[p] = 1;
     for (int j=p+1; j<p+p; j++) { w[j] = 1ll * w[j-1] * pw % MOD; } } }
 for (int i=0; i<len; ++i) if (i < rev[i]) { std::swap(a[i], a[rev[i]]); }
 for (int l=1; l<len; l<<=1) {
   for (int i=0; i<len; i+=2*l) {
     for (int j=0; j<l; ++j) {
       int t = 1ll * a[i + l + j] * w[l + j] % MOD;
       checkAdd(a[i + l + j] = a[i + j] - t);
       checkSub(a[i + j] += t); } } }
}
void idft(int *const a, int n) {
 int len = 1 << n;
 std::reverse(a+1, a+len);
 dft(a, n);
 int inv_len = power(len, MOD-2);
 for (int i=0; i<len; ++i) {
   a[i] = 1ll * a[i] * inv_len % MOD; } }
void mulp(int *const a, int *const b, int _n) {
 int l=1, n=0;
 while (l < 2*_n-1) { l *= 2; n++; }
 dft(a, n); dft(b, n);
 for (int i=0; i<l; ++i) { a[i] = 1ll * a[i] * b[i] % MOD; }
 idft(a, n);
}
}
int fac[N], ifac[N];
int main () {
 n = sc.n(); m = sc.n(); x = sc.n();
 for (int i=0; i<=m; ++i) { a[i] = sc.n(); }
 fac[0]=ifac[0]=1; for (int i=1;i<=m;++i) { fac[i] = 1ll * fac[i-1] * i % MOD; ifac[i] = power(fac[i], MOD-2); }
 for (int i=0; i<=m; ++i) { a[i] = 1ll * a[i] * ifac[i] % MOD; }
 for (int i=0; i<=m; ++i) { b[i] = ifac[i]; if (i % 2) { b[i] = MOD - b[i]; } }
 polys::mulp(a, b, m+1);
 int ans = 0;
 int x_pow = 1, n_down = 1;
 for (int i=0; i<=m; ++i) {
   ans = (ans + 1ll * a[i] * x_pow % MOD * n_down) % MOD;
   x_pow = 1ll * x_pow * x % MOD; n_down = 1ll * n_down * (n-i) % MOD; }
 printf("%d\n", ans);
 return 0;
}



Creative Commons License
This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.