手动博客搬家: 本文发表于20181206 14:42:53, 原地址https://blog.csdn.net/suncongbo/article/details/84853342

题目链接: https://www.luogu.org/problemnew/show/P4512

没想到这算法这么蠢。。一点都不难啊。。我连这都推不出来我是不是没救了

这个多项式满足\(A(x)=B(x)Q(x)+R(x)\), 如果已知\(R(x)\)是\(0\), 那显然很好处理,求个逆就行了。

那如果有余数呢?很简单,如果我们把这个多项式的系数翻转(reverse),那么\(R(x)\)就从低次项变成了高次项,低次项就不再受\(R(x)\)的而影响了。

这是我们的基本思路。下面我们来形式化这个过程:

\(A(x)=B(x)Q(x)+R(x)\)

对于\(n\)次多项式\(F(x)\)令\(F_R(x)=x^nF(\frac{1}{x})\) (这就是前面所说的reverse操作)

则有\(x^nA(\frac{1}{x})=x^mB(\frac{1}{x})x^{n-m}Q(\frac{1}{x})+x^{m-1}R(\frac{1}{x})x^{n-m+1}\)

\(A_R(x)=B_R(x)Q_R(x)+x^{n-m+1}R_R(x)\)

\(A_R(x)\equiv B_R(x)Q_R(x) (\mod x^{n-m+1})\)

于是我们求\(B_R(x)\)在\(\mod x^{n-m+1}\)意义下的逆,然后乘以\(A_R(x)\)即可求出\(Q_R(x)\), 从而得到\(Q(x)\).

然后用\(R(x)=A(x)-B(x)Q(x)\)即可求出\(R(x)\).

(虽然算法简单但是要注意的地方还挺多……容易错。)

时间复杂度\(O(n\log n)\), 我写的进行了\(24\)倍常数的ntt.

空间复杂度\(O(n)\), 我的实现好像需要开\(8\)倍。

代码实现

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#define llong long long
#define modinc(x) {if(x>=P) x-=P;}
using namespace std; const int N = 1<<19;
const int LGN = 19;
const llong G = 3ll;
const int P = 998244353;
llong tmp1[N+3],tmp2[N+3],tmp3[N+3],tmp4[N+3];
llong tmp5[N+3],tmp6[N+3],tmp7[N+3],tmp8[N+3],tmp9[N+3];
llong a[N+3],b[N+3],q[N+3],r[N+3];
int id[N+3];
int n,m; llong quickpow(llong x,llong y)
{
llong cur = x,ret = 1ll;
for(int i=0; y; i++)
{
if(y&(1ll<<i)) {y-=(1ll<<i); ret = ret*cur%P;}
cur = cur*cur%P;
}
return ret;
}
llong mulinv(llong x) {return quickpow(x,P-2)%P;} void initid(int dgr)
{
int len = 0; for(int i=0; i<=LGN; i++) if((1<<i)==dgr) {len = i; break;}
id[0] = 0;
for(int i=1; i<dgr; i++) id[i] = (id[i>>1]>>1)|(i&1)<<(len-1);
} int getdgr(int x)
{
int ret = 1;
while(ret<=x) ret<<=1;
return ret;
} void ntt(int dgr,int coe,llong poly[],llong ret[])
{
initid(dgr);
for(int i=0; i<dgr; i++) ret[i] = poly[i];
for(int i=0; i<dgr; i++) if(i<id[i]) swap(ret[i],ret[id[i]]);
for(int i=1; i<=(dgr>>1); i<<=1)
{
llong tmp = quickpow(G,(P-1)/(i<<1));
if(coe==-1) tmp = mulinv(tmp);
for(int j=0; j<dgr; j+=(i<<1))
{
llong expn = 1ll;
for(int k=0; k<i; k++)
{
llong x = ret[j+k],y = ret[j+i+k]*expn%P;
ret[j+k] = x+y; modinc(ret[j+k]);
ret[j+i+k] = x-y+P; modinc(ret[j+i+k]);
expn = (expn*tmp)%P;
}
}
}
if(coe==-1)
{
llong tmp = mulinv(dgr);
for(int j=0; j<dgr; j++) ret[j] = ret[j]*tmp%P;
}
} void polyinv(int dgr,llong poly[],llong ret[])
{
for(int i=0; i<dgr; i++) ret[i] = 0ll;
ret[0] = mulinv(poly[0]);
for(int i=1; i<=(dgr>>1); i<<=1)
{
for(int j=0; j<(i<<2); j++) tmp1[j] = j<i ? ret[j] : 0ll;
for(int j=0; j<(i<<2); j++) tmp2[j] = j<(i<<1) ? poly[j] : 0ll;
ntt((i<<2),1,tmp1,tmp3); ntt((i<<2),1,tmp2,tmp4);
for(int j=0; j<(i<<2); j++) tmp3[j] = tmp3[j]*tmp3[j]%P*tmp4[j]%P;
ntt((i<<2),-1,tmp3,tmp4);
for(int j=0; j<(i<<1); j++) ret[j] = (tmp1[j]+tmp1[j]-tmp4[j]+P)%P;
}
for(int j=dgr; j<(dgr<<1); j++) ret[j] = 0ll;
} void polyrev(int dgr,llong poly[],llong ret[])
{
for(int i=0; i<dgr; i++) ret[i] = poly[dgr-1-i];
} void polydiv(int dgr1,int dgr2,llong poly1[],llong poly2[],llong ret1[],llong ret2[])
{
int _dgr1 = getdgr(dgr1),_dgr2 = getdgr(dgr2);
polyrev(dgr2,poly2,tmp5); polyrev(dgr1,poly1,tmp9);
polyinv(_dgr1,tmp5,tmp6);
for(int i=dgr1-dgr2+1; i<(_dgr1<<1); i++) tmp6[i] = 0ll;
ntt(_dgr1<<1,1,tmp9,tmp7); ntt(_dgr1<<1,1,tmp6,tmp8);
for(int i=0; i<(_dgr1<<1); i++) tmp7[i] = tmp7[i]*tmp8[i]%P;
ntt(_dgr1<<1,-1,tmp7,tmp8);
for(int i=dgr1-dgr2+1; i<(_dgr1<<1); i++) tmp8[i] = 0ll;
polyrev(dgr1-dgr2+1,tmp8,ret1);
ntt(_dgr1<<1,1,poly2,tmp7); ntt(_dgr1<<1,1,ret1,tmp8);
for(int i=0; i<(_dgr1<<1); i++) tmp7[i] = tmp7[i]*tmp8[i]%P;
ntt(_dgr1<<1,-1,tmp7,ret2);
for(int i=dgr2; i<(_dgr1<<1); i++) ret2[i] = 0ll;
for(int i=0; i<dgr2-1; i++) ret2[i] = (poly1[i]-ret2[i]+P)%P;
} int main()
{
scanf("%d%d",&n,&m); n++; m++;
for(int i=0; i<n; i++) scanf("%lld",&a[i]);
for(int i=0; i<m; i++) scanf("%lld",&b[i]);
int dgr1 = getdgr(n),dgr2 = getdgr(m);
polydiv(n,m,a,b,q,r);
for(int i=0; i<=n-m; i++) printf("%lld ",q[i]); puts("");
for(int i=0; i<m-1; i++) printf("%lld ",r[i]);
return 0;
}

luogu P4512 多项式除法 (模板题、FFT、多项式求逆)的更多相关文章

  1. luogu P4726 多项式指数函数(模板题FFT、多项式求逆、多项式对数函数)

    手动博客搬家: 本文发表于20181127 08:39:42, 原地址https://blog.csdn.net/suncongbo/article/details/84559818 题目链接: ht ...

  2. luogu P4725 多项式对数函数 (模板题、FFT、多项式求逆、求导和积分)

    手动博客搬家: 本文发表于20181125 13:25:03, 原地址https://blog.csdn.net/suncongbo/article/details/84487306 题目链接: ht ...

  3. UVA 796 Critical Links(模板题)(无向图求桥)

    <题目链接> 题目大意: 无向连通图求桥,并将桥按顺序输出. 解题分析: 无向图求桥的模板题,下面用了kuangbin的模板. #include <cstdio> #inclu ...

  4. UVA 315 Network (模板题)(无向图求割点)

    <题目链接> 题目大意: 给出一个无向图,求出其中的割点数量. 解题分析: 无向图求割点模板题. 一个顶点u是割点,当且仅当满足 (1) u为树根,且u有多于一个子树. (2) u不为树根 ...

  5. 2014 HDU多校弟五场A题 【归并排序求逆序对】

    这题是2Y,第一次WA贡献给了没有long long 的答案QAQ 题意不难理解,解题方法不难. 先用归并排序求出原串中逆序对的个数然后拿来减去k即可,如果答案小于0,则取0 学习了归并排序求逆序对的 ...

  6. 线段树菜鸟一题+归并排序【求逆序数】POJ2299

    题目链接:http://poj.org/problem?id=2299 归并排序解法链接:http://blog.csdn.net/lyy289065406/article/details/66473 ...

  7. [洛谷P4721]【模板】分治 FFT_求逆

    题目大意:给定长度为$n-1$的数组$g_{[1,n)}$,求$f_{[0,n)}$,要求: $$f_i=\sum_{j=1}^if_{i-j}g_j\\f_0=1$$ 题解:分治$FFT$博客,发现 ...

  8. 【luogu P3803】【模板】多项式乘法(FFT)

    [模板]多项式乘法(FFT) 题目链接:luogu P3803 题目大意 给你两个多项式,要你求这两个多项式乘起来得到的多项式.(卷积) 思路 系数表示法 就是我们一般来表示一个多项式的方法: \(A ...

  9. P4512 【模板】多项式除法

    思路 多项式除法板子 多项式除法 给出\(A(x)\)和\(B(x)\),求一个\(n-m\)次的多项式\(D(x)\),一个\(m-1\)次多项式\(R(x)\),满足 \[ A(x)=B(x)D( ...

随机推荐

  1. 【你你你你在开玩笑吧】什么叫凭借纯兴趣搞ACM?涨姿势了

        好长时间不扯淡了,今天扯个玩玩,吐个槽.     在上海回济南的列车上,回顾起这两天在携程codingtrip颁奖仪式上大牛们的种种心得,姿势涨了不少,着实涨了不少啊.我这样的渣渣毕竟图样图森 ...

  2. CSS3 网格布局(grid layout)基础知识 - 隐式网格自己主动布局(grid-auto-rows/grid-auto-columns/grid-auto-flow)

    网格模板(grid-template)属性及其普通写法(longhands)定义了一个固定数量的轨道.构成显式网格. 当网格项目定位在这些界限之外.网格容器通过添加隐式网格线生成隐式网格轨道. 这些隐 ...

  3. C# 数据库备份与还原 小妹做了一个winform系统,需要对sql2000数据库备份和还原(小妹妹你太狠了)

      成功了,把代码帖出来给大家看看,跟我刚开始帖出来的差不多,是需要杀掉进程的,我之前调用的存储过程,可能有点问题,现在改成sql了/// <summary>        /// 数据库 ...

  4. hdu1150——最小点覆盖

    As we all know, machine scheduling is a very classical problem in computer science and has been stud ...

  5. 当Shell遇上了Node.js(转载)

    转载:http://developer.51cto.com/art/201202/315066.htm 好吧,我承认,这个标题有点暧昧的基情,但是希望下文的内部能给不熟悉或不喜欢Shell或WIN平台 ...

  6. kafka参数在线修改

    当kafka集群单个节点出现磁盘满了,需要清理历史topic数据:方法如下 1): 停掉kafka进程,将kafka的server.properties中的log.retention.hours=1/ ...

  7. SqlMap常用参数(一)

    sqlmap可谓是利用sql注入的神器了,sqlmap的参数很多,接下介绍几种常见的参数. 一.注入access数据库常用的参数 sqlmap.py -u "url"  //判断参 ...

  8. poj1958-汉诺四塔问题(三种方法)

    链接:http://poj.org/problem?id=1958 大意:汉诺塔升级版,四根柱子,n个盘子,求最少移动次数: 两种方法 递推or递归(当然还有思路3--打表) 思路1:递推(或者DP? ...

  9. POJ 2230 DFS

    题意: Bessie 最近做了农场看守,他每天晚上的工作就是巡视农场并且保证没有坏人破坏农场.从谷仓出发去巡视,并且最终回到谷仓. Bessie 视力不是很好,不能像其他农场的看守一样,对农场的每一条 ...

  10. 【SQL】联合语句

    一.UNION操作符 UNION 操作符用于合并两个结果集,在合并的同时去掉重复行,并按合并后结果的第一列升序排列.合并后结果集的列名由第一个结果集的列名确定. UINON连接的两个结果集必须具有相同 ...