洛谷P4512 【模板】多项式除法

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

题解:http://picks.logdown.com/posts/197262-polynomial-division

备份

用系数反转消去余数?不知道怎么想出来的方法。。

版本1:基于版本2,要求n>=m

  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 void p_div(int *a,int *b,int *c,int n,int m)//c=a/b;deg(a)=n,deg(b)=m,deg(c)=n-m;a,b无前导0;n>=m
141 {
142     reverse(a,a+n+1);reverse(b,b+m+1);
143     int x=n-m+1,t=1;
144     for(;t<x;t<<=1);
145     memset(b+m+1,0,sizeof(int)*max(t-m-1,0));
146     p_inv(b,c,t);
147     memset(c+x,0,sizeof(int)*((t<<1)-x));
148     memset(a+x,0,sizeof(int)*((t<<1)-x));
149     init(t<<1);
150     dft(a,t<<1,1);dft(c,t<<1,1);
151     for(int i=0;i<(t<<1);++i)
152         c[i]=ull(c[i])*a[i]%md;
153     dft(c,t<<1,-1);
154     memset(c+(n-m+1),0,sizeof(int)*((t<<1)-n+m-1));
155     reverse(c,c+x);
156 }
157 void p_divmod(int *a,int *b,int *c,int *d,int n,int m)//c=a/b,d=a%b,deg(d)=(<=)m-1;其余同上
158 {
159     static int t1[N];
160     memcpy(d,a,sizeof(int)*(m+1));
161     int x=n+1,t=1;
162     for(;t<x;t<<=1);
163     memcpy(t1,b,sizeof(int)*(m+1));
164     memset(t1+m+1,0,sizeof(int)*max(t-m-1,0));
165     p_div(a,b,c,n,m);
166     memcpy(a,c,sizeof(int)*(n-m+1));
167     memset(a+n-m+1,0,sizeof(int)*(t-n+m-1));
168     init(t);
169     dft(a,t,1);dft(t1,t,1);
170     for(int i=0;i<t;++i)
171         t1[i]=ull(t1[i])*a[i]%md;
172     dft(t1,t,-1);
173     for(int i=0;i<=m;++i)
174         delto(d[i],t1[i]);
175 }
176 int a[N],b[N],c[N],d[N];
177 int n,m;
178 //int a1[N],b1[N],c1[N],d1[N];
179 int main()
180 {
181     int i;
182     inv[1]=1;
183     for(i=2;i<=300000;++i)
184         inv[i]=ull(md-md/i)*inv[md%i]%md;
185     scanf("%d%d",&n,&m);
186     for(i=0;i<=n;++i)
187         scanf("%d",a+i);
188     for(i=0;i<=m;++i)
189         scanf("%d",b+i);
190     //memcpy(a1,a,sizeof(a1));
191     //memcpy(b1,b,sizeof(b1));
192     //p_divmod(a,b,c,d,n,m);
193     //memcpy(a,a1,sizeof(int)*(n+1));
194     //memcpy(b,b1,sizeof(int)*(m+1));
195     p_divmod(a,b,c,d,n,m);
196     for(i=0;i<=n-m;++i)
197         printf("%d ",c[i]);
198     puts("");
199     for(i=0;i<=m-1;++i)
200         printf("%d ",d[i]);
201     return 0;
202 }
View Code
原文地址:https://www.cnblogs.com/hehe54321/p/10583745.html