题意:给定 m 次多项式 f(x) ,求 ∑nk=0f(k)(nk)xk(1−x)n−k 。
老年选手石乐志看不出二项式展开的悲惨经历
【搞笑做法】
考虑多项式 f(x)=∑kakxk 代入原式,将 xk(1−x)n−k 换成 xnyk ,有
要不是我不(lan)会(de)写(xie)快速插值可能就上这玩意了。。。
秉着【出题人一定不会写这么毒瘤的东西】的想法直接用点值来推。。。也能做。。而且复杂度更优秀了。。(当然是在给了点值的情况下。。。)
【正常(?)做法】
考虑 f(x) 的牛顿表示,将系数反演后代入,得
【主要代码】
int N , len;
arr rev , wn , f , e;
inline void init(int n , int m) {
for (N = 1 , len = 0; N <= n + m; N <<= 1 , len ++);
For (i , 0 , N) rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << (len - 1));
int g = Pow(G , (mod - 1) / N);
wn[0] = 1; For (i , 1 , N) wn[i] = mul(wn[i - 1] , g);
}
inline void dft(int *a , int n , int v) {
For (i , 0 , n) if (i < rev[i]) swap(a[i] , a[rev[i]]);
for (int s = 2 , i = 1; s <= n; s <<= 1 , i ++) {
int g = wn[1 << (len - i)];
for (int k = 0; k < n; k += s) {
int w = 1;
For (j , 0 , s / 2) {
int u = a[k + j] , t = mul(w , a[k + j + s / 2]);
a[k + j] = add(u , t) , a[k + j + s / 2] = dec(u , t);
w = mul(w , g);
}
}
}
if (v == -1) {
int w = Pow(n , mod - 2);
For (i , 0 , n) a[i] = mul(a[i] , w);
}
}
int n , m , x;
arr frac , invF;
void input() {
n = rd() , m = rd() , x = rd();
frac[0] = 1;
rep (i , 1 , m) frac[i] = mul(frac[i - 1] , i);
invF[m] = Pow(frac[m] , mod - 2);
per (i , m , 1) invF[i - 1] = mul(invF[i] , i);
rep (i , 0 , m) f[i] = mul(rd() , invF[i]);
rep (i , 0 , m) e[i] = (i & 1) ? mod - invF[i] : invF[i];
}
void solve() {
init(m , m);
dft(f , N , 1) , dft(e , N , 1);
For (i , 0 , N) f[i] = mul(f[i] , e[i]);
reverse(wn + 1 , wn + N);
dft(f , N , -1);
int ans = 0;
int ff = 1 , tt = 1;
rep (i , 0 , m) {
int tmp = mul(ff , tt);
tmp = mul(tmp , f[i]);
ans = add(ans , tmp);
ff = mul(ff , n - i);
tt = mul(tt , x);
}
printf("%d\n" , ans);
}