【BZOJ 4734】【UOJ 269】【清华集训2016】 如何优雅地求和

来源:互联网 发布:莱州广电网络 编辑:程序博客网 时间:2024/05/02 06:11

题意:给定m次多项式f(x),求nk=0f(k)(nk)xk(1x)nk

老年选手石乐志看不出二项式展开的悲惨经历

【搞笑做法】
考虑多项式f(x)=kakxk代入原式,将xk(1x)nk换成xnyk,有

xnjajk(nk)ykkj

gn(m)=k(nk)ykkm,则
gn(m)=k((n1k)+(n1k1))ykkm=gn1(m)+yj(mj)gn1(j)

Gn(z)=kgn(k)zk/k!,则Gn(z)=(yez+1)Gn1(z)
于是多项式快速幂即可。。。。理论上这里是O(mlogm)的。。。常数顶两个log
然而这个题他多项式给的是点值。。。所以要这么做的话还得写个快速插值。。。
这样就成功把所有多项式操作都写进来啦
复杂度就变成了O(mlog2m)。。。

要不是我不(lan)会(de)写(xie)快速插值可能就上这玩意了。。。
秉着【出题人一定不会写这么毒瘤的东西】的想法直接用点值来推。。。也能做。。而且复杂度更优秀了。。(当然是在给了点值的情况下。。。)

【正常(?)做法】
考虑f(x)的牛顿表示,将系数反演后代入,得

answer=k=0nj=0mi=0j(1)ji(ji)f(i)(kj)(nk)xk(1x)nk=j=0m(i(ji)(1)jif(j))(k=0(nk)(kj)xk(1x)nk)=j=0m(nj)j!([zj]E(z)F(z))(k=0(njkj)xk(1x)nk)=j=0m(nj)j!([zj]E(z)F(z))(k=0nj(njk)xk+j(1x)njk)=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只出到了2e4啊。。。怕不是std真的是上面那个搞笑做法。。。

【主要代码】

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);}
阅读全文
0 0
原创粉丝点击