多项式exp

引入

求解 系数对一个数取模 。

前置知识

  • 泰勒展开, 这个相信学习过高数的朋友都知道。
  • 牛顿迭代,我们可以通过牛顿迭代找出一个函数的零点,当然这个是有一定限制的,这个可以百度搜一下。换句话就是已知 ,要求求出满足 的多项式 。考虑倍增,如果我们已经知道 。那么根据泰勒展开 因为 的前 项为 ,那么在 的意义下前 项为 。所以 变形之后 。 如此我们就得到了牛顿迭代法的公式。

    推导

    。先做一些简单的变形 那么定义 那么其实我们就是要求出这个函数的零点。代入上面的牛顿迭代的式中可以得到

    代码

    #include<bits/stdc++.h>
    using namespace std;
    const int N = 4e6 + 100,P = 998244353;
    int limit,r[N],L;
    int ksm(int a,int b) {int x=1;for(;b;b>>=1,a=1LL*a*a%P)if(b&1)x=1LL*x*a%P;return x;}
    void NTT(int *a,int type) {
      for(int i=0;i<limit;i++)if(i>r[i])swap(a[i],a[r[i]]);
      for(int mid=1;mid<limit;mid<<=1) {
          int wn=ksm(3,(P-1)/(mid<<1));for(int i=0;i<limit;i+=(mid<<1)){
              for(int j=0,w=1;j<mid;j++,w=1LL*w*wn%P) {
                  int x=a[i+j],y=1LL*a[i+j+mid]*w%P;
                  a[i+j]=(x+y)%P;a[i+j+mid]=(x-y+P)%P;
              }
          }
      }
      if(type==-1) {reverse(a+1,a+limit);int Inv=ksm(limit,P-2);for(int i=0;i<limit;i++)a[i]=1LL*a[i]*Inv%P;}
    }
    void Mul(int *f,int *g,int len) {
      static int G[N];
      memcpy(G,g,sizeof(G));
      NTT(f,1);NTT(g,1);
      for(int i = 0;i < limit;i++) f[i] = 1LL * f[i] * g[i] % P;
      NTT(f,-1);for(int i=len+1;i<limit;i++) f[i]=0;
    }
    void init(int len) {
      limit=1;L=0;while(limit<=len)limit<<=1,L++;
      for(int i=0;i<limit;i++)r[i]=(r[i>>1]>>1)|((i&1)<<L-1);
    }
    void GetInv(int *f,int *g,int n) {
      if(n==1) {g[0]=ksm(f[0],P-2);return;}
      GetInv(f,g,(n+1)>>1);
      init(n+n-2);
      static int c[N];memset(c,0,sizeof(c));
      for(int i = 0;i < n;i++) c[i] = f[i];
      NTT(c,1);NTT(g,1);
      for(int i = 0;i < limit;i++) g[i] = 1LL * g[i] * ((2LL - 1LL * c[i] * g[i] % P + P) % P) % P;
      NTT(g,-1);for(int i = n;i < limit;i++) g[i] = 0;
    }
    void Dao(int *f,int *g,int n) {
      for(int i = 1;i < n;i++) g[i-1]=1LL*f[i]*i%P;g[n-1]=0;
    }
    void JiFen(int *f,int *g,int n) {
      for(int i = 1;i < n;i++) g[i]=1LL*f[i-1]*ksm(i,P-2)%P;g[0]=0; 
    }
    void GetLn(int *f,int *g,int n) {
      static int A[N],B[N];memset(A,0,sizeof(A));memset(B,0,sizeof(B));
      Dao(f,A,n);GetInv(f,B,n);
      init(n+n-2);NTT(A,1);NTT(B,1);
      for(int i=0;i<limit;i++)A[i]=1LL*A[i]*B[i]%P;
      NTT(A,-1);JiFen(A,g,n);
    }
    void GetExp(int *f,int *g,int n) {
      if(n==1) {g[0]=1;return;}
      GetExp(f,g,(n+1)>>1);static int F[N];
      memset(F,0,sizeof(F));GetLn(g,F,n);
      F[0]=(1LL*f[0]+1-F[0]+P)%P;
      for(int i=1;i<n;i++)F[i]=(-1LL*F[i]+f[i]+P)%P;
      init(n+n-2);Mul(g,F,n-1);
    }
    int f[N],g[N];
    int main() {
      int n;
      cin >> n;for(int i = 0;i < n;i++) cin >> f[i];
      GetExp(f,g,n);
      for(int i = 0;i < n;i++) cout << g[i] << " ";
      return 0;
    }
数学 文章被收录于专栏

关于多项式

全部评论
%%%
点赞 回复 分享
发布于 2020-10-15 20:45

相关推荐

10-05 11:11
海南大学 Java
投票
理想江南137:感觉挺真诚的 感觉可以试一试
点赞 评论 收藏
分享
10-09 00:50
已编辑
长江大学 算法工程师
不期而遇的夏天:1.同学你面试评价不错,概率很大,请耐心等待;2.你的排名比较靠前,不要担心,耐心等待;3.问题不大,正在审批,不要着急签其他公司,等等我们!4.预计9月中下旬,安心过节;5.下周会有结果,请耐心等待下;6.可能国庆节前后,一有结果我马上通知你;7.预计10月中旬,再坚持一下;8.正在走流程,就这两天了;9.同学,结果我也不知道,你如果查到了也告诉我一声;10.同学你出线不明朗,建议签其他公司保底!11.同学你找了哪些公司,我也在找工作。
点赞 评论 收藏
分享
4 1 评论
分享
牛客网
牛客企业服务