题意:给定
m
次多项式
老年选手石乐志看不出二项式展开的悲惨经历
【搞笑做法】
考虑多项式
f(x)=∑kakxk
代入原式,将
xk(1−x)n−k
换成
xnyk
,有
xn∑jaj∑k(nk)ykkj
设 gn(m)=∑k(nk)ykkm ,则
gn(m)=∑k((n−1k)+(n−1k−1))ykkm=gn−1(m)+y∑j(mj)gn−1(j)
设 Gn(z)=∑kgn(k)zk/k! ,则 Gn(z)=(yez+1)Gn−1(z) 。
于是多项式快速幂即可。。。。理论上这里是 O(mlogm) 的。。。
然而这个题他多项式给的是点值。。。所以要这么做的话还得写个快速插值。。。
复杂度就变成了 O(mlog2m) 。。。
要不是我不(lan)会(de)写(xie)快速插值可能就上这玩意了。。。
秉着【出题人一定不会写这么毒瘤的东西】的想法直接用点值来推。。。也能做。。而且复杂度更优秀了。。(当然是在给了点值的情况下。。。)
【正常(?)做法】
考虑
f(x)
的牛顿表示,将系数反演后代入,得
answer=∑k=0n∑j=0m∑i=0j(−1)j−i(ji)f(i)(kj)(nk)xk(1−x)n−k=∑j=0m(∑i(ji)(−1)j−if(j))(∑k=0(nk)(kj)xk(1−x)n−k)=∑j=0m(nj)j!([zj]E(z)F(z))(∑k=0(n−jk−j)xk(1−x)n−k)=∑j=0m(nj)j!([zj]E(z)F(z))(∑k=0n−j(n−jk)xk+j(1−x)n−j−k)=∑j=0m(nj)j!xj[zj]E(z)F(z)
其中 E(z)=∑k(−1)kzk/k!,F(z)=∑kf(k)/k! 。
于是只需要算 E(Z) 和 F(Z) 的卷积即可。。。时间复杂度就变成了 O(mlogm) 。。。
不太懂为啥 m 只出到了
【主要代码】
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);
}