• 洛谷P5205 【模板】多项式开根


    https://www.luogu.org/problemnew/show/P5205

    按道理说,多项式开根可以有多个解(根据常数项不同有不同的解)。此题只需要输出常数项为1的解(题面漏了)

    首先,可以直接多项式快速幂做(2对998244353的逆元)次幂(直接做只能在输入常数项为1时)(我不是很懂为什么能起效,不过的确能AC)

    版本1:基于版本1

      1 #prag
      2 ma GCC optimize(2)
      3 #include<cstdio>
      4 #include<algorithm>
      5 #include<cstring>
      6 #include<vector>
      7 #include<cmath>
      8 using namespace std;
      9 #define fi first
     10 #define se second
     11 #define mp make_pair
     12 #define pb push_back
     13 typedef long long ll;
     14 typedef unsigned long long ull;
     15 const int md=998244353;
     16 const int N=262144;
     17 #define delto(a,b) ((a)-=(b),((a)<0)&&((a)+=md))
     18 inline int del(int a,int b)
     19 {
     20     a-=b;
     21     return a<0?a+md:a;
     22 }
     23 int rev[N];
     24 void init(int len)
     25 {
     26     int bit=0,i;
     27     while((1<<(bit+1))<=len)    ++bit;
     28     for(i=1;i<len;++i)
     29         rev[i]=(rev[i>>1]>>1)|((i&1)<<(bit-1));
     30 }
     31 ull poww(ull a,ull b)
     32 {
     33     ull ans=1;
     34     for(;b;b>>=1,a=a*a%md)
     35         if(b&1)
     36             ans=ans*a%md;
     37     return ans;
     38 }
     39 int inv[300011];
     40 void dft(int *a,int len,int idx)//要求len为2的幂
     41 {
     42     int i,j,k,t1,t2;ull wn,wnk;
     43     for(i=0;i<len;++i)
     44         if(i<rev[i])
     45             swap(a[i],a[rev[i]]);
     46     for(i=1;i<len;i<<=1)
     47     {
     48         wn=poww(idx==1?3:332748118,(md-1)/(i<<1));
     49         for(j=0;j<len;j+=(i<<1))
     50         {
     51             wnk=1;
     52             for(k=j;k<j+i;++k,wnk=wnk*wn%md)
     53             {
     54                 t1=a[k];t2=a[k+i]*wnk%md;
     55                 a[k]+=t2;
     56                 (a[k]>=md)&&(a[k]-=md);
     57                 a[k+i]=t1-t2;
     58                 (a[k+i]<0)&&(a[k+i]+=md);
     59             }
     60         }
     61     }
     62     if(idx==-1)
     63     {
     64         ull ilen=inv[len];
     65         for(i=0;i<len;++i)
     66             a[i]=a[i]*ilen%md;
     67     }
     68 }
     69 void p_inv(int *f,int *g,int len)//g=f^(-1);f,g数组的长度不小于2len(需要足够长用于临时存放元素);要求len是2的幂
     70 {
     71     static int t1[N],t2[N];
     72     g[0]=poww(f[0],md-2);
     73     for(int i=2,j;i<=len;i<<=1)
     74     {
     75         memcpy(t1,f,sizeof(int)*i);
     76         memcpy(t2,g,sizeof(int)*(i>>1));
     77         memset(t2+(i>>1),0,sizeof(int)*(i>>1));
     78         init(i);
     79         dft(t1,i,1);dft(t2,i,1);
     80         for(j=0;j<i;++j)
     81             t1[j]=ull(t1[j])*t2[j]%md;
     82         dft(t1,i,-1);
     83         for(j=0;j<(i>>1);++j)
     84             t1[j]=t1[j+(i>>1)];
     85         memset(t1+(i>>1),0,sizeof(int)*(i>>1));
     86         dft(t1,i,1);
     87         for(j=0;j<i;++j)
     88             t1[j]=ull(t1[j])*t2[j]%md;
     89         dft(t1,i,-1);
     90         for(j=i>>1;j<i;++j)
     91             g[j]=md-t1[j-(i>>1)];
     92     }
     93 }
     94 inline void p_de(int *f,int len)//derivative求导;f=f'
     95 {
     96     for(int i=0;i<len-1;++i)
     97         f[i]=ull(i+1)*f[i+1]%md;
     98     f[len-1]=0;
     99 }
    100 inline void p_in(int *f,int len)//integral积分;f=?f
    101 {
    102     for(int i=len-1;i>=1;--i)
    103         f[i]=ull(f[i-1])*inv[i]%md;
    104     f[0]=0;
    105 }
    106 void p_ln(int *f,int len)//要求len为2的幂,f[0]=1
    107 {
    108     static int t3[N];
    109     p_inv(f,t3,len);p_de(f,len);
    110     init(len<<1);
    111     dft(f,len<<1,1);dft(t3,len<<1,1);
    112     for(int i=0;i<(len<<1);++i)
    113         f[i]=ull(f[i])*t3[i]%md;
    114     dft(f,len<<1,-1);p_in(f,len);
    115 }
    116 void p_exp(int *f,int *g,int len)//要求len为2的幂,f[0]=0
    117 {
    118     static int t1[N],t2[N];
    119     g[0]=1;
    120     for(int i=2,j;i<=len;i<<=1)
    121     {
    122         memcpy(t1,g,sizeof(int)*(i>>1));
    123         memset(t1+(i>>1),0,sizeof(int)*(i>>1));
    124         p_ln(t1,i);
    125         for(j=0;j<(i>>1);++j)
    126             t1[j]=del(f[j+(i>>1)],t1[j+(i>>1)]);
    127         memset(t1+(i>>1),0,sizeof(int)*(i>>1));
    128         init(i);
    129         dft(t1,i,1);
    130         memcpy(t2,g,sizeof(int)*(i>>1));
    131         memset(t2+(i>>1),0,sizeof(int)*(i>>1));
    132         dft(t2,i,1);
    133         for(j=0;j<i;++j)
    134             t1[j]=ull(t1[j])*t2[j]%md;
    135         dft(t1,i,-1);
    136         for(j=i>>1;j<i;++j)
    137             g[j]=t1[j-(i>>1)];
    138     }
    139 }
    140 inline void p_pow_1(int *f,int *g,int len,int b)//要求len为2的幂,常数项为1
    141 {
    142     p_ln(f,len);
    143     for(int i=0;i<len;++i)
    144         f[i]=ull(f[i])*b%md;
    145     p_exp(f,g,len);
    146 }
    147 void p_pow(int *f,int *g,int len,int b)//g=f^b;要求len为2的幂
    148 {
    149     int i;ll p=-1;
    150     for(i=0;i<len;++i)
    151         if(f[i])
    152         {
    153             p=i;
    154             break;
    155         }
    156     if(p==-1)    return;
    157     for(i=0;i<len-p;++i)
    158         f[i]=f[i+p];
    159     memset(f+len-p,0,sizeof(int)*p);
    160     int t=f[0],t1=poww(t,md-2),t2=poww(t,b);
    161     for(i=0;i<len;++i)
    162         f[i]=ull(f[i])*t1%md;
    163     p_pow_1(f,g,len,b);
    164     for(i=0;i<len;++i)
    165         g[i]=ull(g[i])*t2%md;
    166     p*=b;
    167     for(i=len-1;i>=p;--i)
    168         g[i]=g[i-p];
    169     memset(g,0,sizeof(int)*min(ll(len),p));
    170 }
    171 int a[N],b[N];
    172 int n,n1;
    173 int main()
    174 {
    175     int i,t;
    176     inv[1]=1;
    177     for(i=2;i<=300000;++i)
    178         inv[i]=ull(md-md/i)*inv[md%i]%md;
    179     scanf("%d",&n);n1=n;
    180     for(i=0;i<n;++i)
    181         scanf("%d",a+i);
    182     for(t=1;t<n;t<<=1);
    183     n=t;
    184     p_pow(a,b,n,499122177);
    185     for(i=0;i<n1;++i)
    186         printf("%d ",b[i]);
    187     return 0;
    188 }
    View Code

    也可以直接牛顿迭代做。设$g(f(x))=f(x)^2-A(x)$

    $f(x)=f_0(x)-frac{f_0(x)^2-A(x)}{2f_0(x)}=frac{A(x)}{2f_0(x)}+frac{f_0(x)}{2}$

    版本2:基于版本2

      1 #prag
      2 ma GCC optimize(2)
      3 #include<cstdio>
      4 #include<algorithm>
      5 #include<cstring>
      6 #include<vector>
      7 #include<cmath>
      8 using namespace std;
      9 #define fi first
     10 #define se second
     11 #define mp make_pair
     12 #define pb push_back
     13 typedef long long ll;
     14 typedef unsigned long long ull;
     15 const int md=998244353;
     16 const int N=262144;
     17 #define addto(a,b) ((a)+=(b),((a)>=md)&&((a)-=md))
     18 #define delto(a,b) ((a)-=(b),((a)<0)&&((a)+=md))
     19 inline int del(int a,int b)
     20 {
     21     a-=b;
     22     return a<0?a+md:a;
     23 }
     24 int rev[N];
     25 void init(int len)
     26 {
     27     int bit=0,i;
     28     while((1<<(bit+1))<=len)    ++bit;
     29     for(i=1;i<len;++i)
     30         rev[i]=(rev[i>>1]>>1)|((i&1)<<(bit-1));
     31 }
     32 ull poww(ull a,ull b)
     33 {
     34     ull ans=1;
     35     for(;b;b>>=1,a=a*a%md)
     36         if(b&1)
     37             ans=ans*a%md;
     38     return ans;
     39 }
     40 int inv[300011];
     41 void dft(int *a,int len,int idx)//要求len为2的幂
     42 {
     43     int i,j,k,t1,t2;ull wn,wnk;
     44     for(i=0;i<len;++i)
     45         if(i<rev[i])
     46             swap(a[i],a[rev[i]]);
     47     for(i=1;i<len;i<<=1)
     48     {
     49         wn=poww(idx==1?3:332748118,(md-1)/(i<<1));
     50         for(j=0;j<len;j+=(i<<1))
     51         {
     52             wnk=1;
     53             for(k=j;k<j+i;++k,wnk=wnk*wn%md)
     54             {
     55                 t1=a[k];t2=a[k+i]*wnk%md;
     56                 a[k]+=t2;
     57                 (a[k]>=md)&&(a[k]-=md);
     58                 a[k+i]=t1-t2;
     59                 (a[k+i]<0)&&(a[k+i]+=md);
     60             }
     61         }
     62     }
     63     if(idx==-1)
     64     {
     65         ull ilen=inv[len];
     66         for(i=0;i<len;++i)
     67             a[i]=a[i]*ilen%md;
     68     }
     69 }
     70 void p_inv(int *f,int *g,int len)//g=f^(-1);f,g数组的长度不小于2len(需要足够长用于临时存放元素);要求len是2的幂
     71 {
     72     static int t1[N],t2[N];
     73     g[0]=poww(f[0],md-2);
     74     for(int i=2,j;i<=len;i<<=1)
     75     {
     76         memcpy(t1,f,sizeof(int)*i);
     77         memcpy(t2,g,sizeof(int)*(i>>1));
     78         memset(t2+(i>>1),0,sizeof(int)*(i>>1));
     79         init(i);
     80         dft(t1,i,1);dft(t2,i,1);
     81         for(j=0;j<i;++j)
     82             t1[j]=ull(t1[j])*t2[j]%md;
     83         dft(t1,i,-1);
     84         for(j=0;j<(i>>1);++j)
     85             t1[j]=t1[j+(i>>1)];
     86         memset(t1+(i>>1),0,sizeof(int)*(i>>1));
     87         dft(t1,i,1);
     88         for(j=0;j<i;++j)
     89             t1[j]=ull(t1[j])*t2[j]%md;
     90         dft(t1,i,-1);
     91         for(j=i>>1;j<i;++j)
     92             g[j]=md-t1[j-(i>>1)];
     93     }
     94 }
     95 inline void p_de(int *f,int len)//derivative求导;f=f'
     96 {
     97     for(int i=0;i<len-1;++i)
     98         f[i]=ull(i+1)*f[i+1]%md;
     99     f[len-1]=0;
    100 }
    101 inline void p_in(int *f,int len)//integral积分;f=?f
    102 {
    103     for(int i=len-1;i>=1;--i)
    104         f[i]=ull(f[i-1])*inv[i]%md;
    105     f[0]=0;
    106 }
    107 void p_ln(int *f,int len)//要求len为2的幂,f[0]=1
    108 {
    109     static int t3[N];
    110     p_inv(f,t3,len);p_de(f,len);
    111     init(len<<1);
    112     dft(f,len<<1,1);dft(t3,len<<1,1);
    113     for(int i=0;i<(len<<1);++i)
    114         f[i]=ull(f[i])*t3[i]%md;
    115     dft(f,len<<1,-1);p_in(f,len);
    116 }
    117 void p_exp(int *f,int *g,int len)//要求len为2的幂,f[0]=0
    118 {
    119     static int t1[N],t2[N];
    120     g[0]=1;
    121     for(int i=2,j;i<=len;i<<=1)
    122     {
    123         memcpy(t1,g,sizeof(int)*(i>>1));
    124         memset(t1+(i>>1),0,sizeof(int)*(i>>1));
    125         p_ln(t1,i);
    126         for(j=0;j<(i>>1);++j)
    127             t1[j]=del(f[j+(i>>1)],t1[j+(i>>1)]);
    128         memset(t1+(i>>1),0,sizeof(int)*(i>>1));
    129         init(i);
    130         dft(t1,i,1);
    131         memcpy(t2,g,sizeof(int)*(i>>1));
    132         memset(t2+(i>>1),0,sizeof(int)*(i>>1));
    133         dft(t2,i,1);
    134         for(j=0;j<i;++j)
    135             t1[j]=ull(t1[j])*t2[j]%md;
    136         dft(t1,i,-1);
    137         for(j=i>>1;j<i;++j)
    138             g[j]=t1[j-(i>>1)];
    139     }
    140 }
    141 void p_sqrt(int *f,int *g,int len)//g=sqrt(f);要求len为2的幂,f[0]=1
    142 {
    143     static int t1[N],t2[N];
    144     g[0]=1;
    145     for(int i=2,j;i<=len;i<<=1)
    146     {
    147         memcpy(t1,g,sizeof(int)*(i>>1));
    148         memset(t1+(i>>1),0,sizeof(int)*(i>>1));
    149         for(j=0;j<i;++j)
    150             addto(t1[j],t1[j]);
    151         p_inv(t1,t2,i);
    152         memset(t2+i,0,sizeof(int)*i);
    153         memcpy(t1,f,sizeof(int)*i);
    154         memset(t1+i,0,sizeof(int)*i);
    155         init(i<<1);
    156         dft(t1,i<<1,1);dft(t2,i<<1,1);
    157         for(j=0;j<(i<<1);++j)
    158             t1[j]=ull(t1[j])*t2[j]%md;
    159         dft(t1,i<<1,-1);
    160         for(j=0;j<(i>>1);++j)
    161             g[j]=(ull(g[j])*499122177+t1[j])%md;
    162         memcpy(g+(i>>1),t1+(i>>1),sizeof(int)*(i>>1));
    163     }
    164 }
    165 int a[N],b[N];
    166 int n,n1;
    167 int main()
    168 {
    169     int i,t;
    170     inv[1]=1;
    171     for(i=2;i<=300000;++i)
    172         inv[i]=ull(md-md/i)*inv[md%i]%md;
    173     scanf("%d",&n);n1=n;
    174     for(i=0;i<n;++i)
    175         scanf("%d",a+i);
    176     for(t=1;t<n;t<<=1);
    177     n=t;
    178     p_sqrt(a,b,n);
    179     for(i=0;i<n1;++i)
    180         printf("%d ",b[i]);
    181     return 0;
    182 }
    View Code
  • 相关阅读:
    分时段查询数据
    优秀产品经理的7大核心技能
    控制台打印螺旋数组
    强大的jquery,再次让我为之鼓掌——三维展示插件
    立象条码打印机PPLB类单双标签打印
    一次与德国程序员的交流
    用ASP为Discuz扩展点小功能
    GDI+ 小破孩动画
    回应YeanJay同学jQuery按钮改变DIV背景色
    C# Dock Style 设置
  • 原文地址:https://www.cnblogs.com/hehe54321/p/10583172.html
Copyright © 2020-2023  润新知