手动博客搬家: 本文发表于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. 泛型和面向对象C++

    1. 在类内部定义的函数默觉得inline,内联函数应该在头文件里定义,由于其定义对编译器必须是可见的,以便编译器可以在调用点内联展开该函数的代码. 此时,仅有函数原型是不够的. 2.assert 3 ...

  2. B1076 [SCOI2008]奖励关 状压dp&&期望dp

    这个题的n<15,一看就是状压dp.但是状态不是很好想.f[][]存i关的状态j. 这个题另一个关键思想在于倒推,我一开始想的是正推,但是只能记忆化了. 题干: 题目描述 你正在玩你最喜欢的电子 ...

  3. bzoj 1800 & 洛谷 P2165 [AHOI2009]飞行棋 —— 模拟

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1800   https://www.luogu.org/problemnew/show/P21 ...

  4. bzoj4034 [HAOI2015]树上操作——树链剖分

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4034 树剖裸题: 一定要注意 long long !!! update 的时候别忘了 pus ...

  5. 快速排序及三向切分快排——java实现

    快速排序也是一种分治算法.主要思想是选取一个切分点,将大于切分点的元素都放置到数组右侧,小于切分点的元素都放置到数组左侧:然后递归,再对切分点左侧和右侧分别排序. 归并排序时递归在前,归并在后,快速排 ...

  6. [Apple开发者帐户帮助]六、配置应用服务(2)创建DeviceCheck私钥

    要验证与DeviceCheck服务的通信,您将使用启用了DeviceCheck的私钥. 首先创建并下载启用了DeviceCheck 的私钥.然后获取密钥标识符(kid)以创建JSON Web令牌(JW ...

  7. HTML中常用的颜色词汇

    white (白色). black(黑色) . blue(蓝色) . green(绿色) .red(红色) .yellow(黄色) . pink(粉色).gray(灰色).brown(棕色). gre ...

  8. IE兼容性測試軟件

    对于前端开发工程师来说,确保代码在各种主流浏览器的各个版本中都能正常工作是件很费时的事情,幸运的是,有很多优秀的工具可以帮助测试浏览器的兼容性,让我们一起看看这些很棒的工具. Spoon Browse ...

  9. Shiro图解

  10. Redis学习笔记(四)-数据类型之list类型

    redis的list类型其实就是一个每个子元素都是string类型的双向链表.所以[lr]push和[lr]pop命令的算法时间复杂度都是O(1).另外list会记录链表的长度.所以llen操作也是O ...