多项式除法&取模

除法&取模
设 $n$ 次多项式 $F(x)$ 和 $m$ 次多项式 $G(x)$ ,求 $n-m$ 次多项式 $Q(x)$ 和 $m-1$ 次多项式 $R(x)$ 满足$$F(x)=G(x)Q(x)+R(x)$$
于是我们有 $$F(\frac{1}{x})=G(\frac{1}{x})Q(\frac{1}{x})+R(\frac{1}{x})$$
两遍同乘 $x^n$ : $$x^nF(\frac{1}{x})=x^mG(\frac{1}{x})x^{n-m}Q(\frac{1}{x})+x^{n-m+1}x^{m-1}R(\frac{1}{x})$$
对于 $n$ 次多项式 $A(x)$ , $x^nA(\frac{1}{x})$ 代表的是多项式系数对称交换,设其为 $a(x)$,则$$f(x)=g(x)q(x)+x^{n-m+1}r(x)$$
由于 $Q(x)$ 是 $n-m$ 次多项式,于是式子满足$$f(x)\equiv g(x)q(x) \pmod{x^{n-m+1}}$$
于是$$q(x)\equiv \frac{f(x)}{g(x)} \pmod{x^{n-m+1}}$$
多项式求逆即可
于是我们可以求出 $Q(x)$ ,根据定义求出 $R(x)$ 即可

代码

#include <bits/stdc++.h>
using namespace std;
const int N=6e5+5,P=998244353;
int n,m,f[N],g[N],G[2]={3,(P+1)/3},A[N],B[N],t,p,re[N],d[N],q[N];
int X(int x){return x>=P?x-P:x;}
int K(int x,int y){
    int z=1;
    for (;y;y>>=1,x=1ll*x*x%P)
        if (y&1) z=1ll*z*x%P;
    return z;
}
void put(int *a,int l){
    for (int i=0;i<=l;i++)
        printf("%d",a[i]),
        putchar(i<l?‘ ‘:‘\n‘);
}
void pre(int l){
    for (t=1,p=0;t<l;t<<=1,p++);
    for (int i=0;i<t;i++)
        re[i]=(re[i>>1]>>1)|((i&1)<<(p-1));
}
void Ntt(int *a,int o){
    for (int i=0;i<t;i++)
        if (i<re[i]) swap(a[i],a[re[i]]);
    for (int wn,i=1;i<t;i<<=1){
        wn=K(G[o],(P-1)/(i<<1));
        for (int x,y,j=0;j<t;j+=(i<<1))
            for (int w=1,k=0;k<i;k++,w=1ll*w*wn%P)
                x=a[j+k],y=1ll*w*a[i+j+k]%P,
                a[j+k]=X(x+y),a[i+j+k]=X(x-y+P);
    }
    if (o)
        for (int i=0,v=K(t,P-2);i<t;i++)
            a[i]=1ll*a[i]*v%P;
}
void inv(int *a,int *b,int l){
    if (l==1){
        b[0]=K(a[0],P-2);
        return;
    }
    inv(a,b,(l+1)>>1);
    for (int i=0;i<l;i++)
        A[i]=a[i],B[i]=b[i];
    pre(l<<1);Ntt(A,0);Ntt(B,0);
    for (int i=0;i<t;i++)
        A[i]=1ll*A[i]*B[i]%P*B[i]%P;
    Ntt(A,1);
    for (int i=0;i<l;i++)
        b[i]=X(X(b[i]<<1)+P-A[i]);
    for (int i=0;i<t;i++) A[i]=B[i]=0;
}
void dvs(int *f,int *g,int *q,int *d){
    reverse(f,f+n+1);reverse(g,g+m+1);
    inv(g,q,n-m+1);
    for (int i=0;i<=n-m;i++)
        A[i]=q[i],B[i]=f[i];
    pre((n-m+1)<<1);Ntt(A,0);Ntt(B,0);
    for (int i=0;i<t;i++)
        A[i]=1ll*A[i]*B[i]%P;
    Ntt(A,1);
    for (int i=0;i<=n-m;i++) q[i]=A[i];
    for (int i=0;i<t;i++) A[i]=B[i]=0;
    reverse(q,q+n-m+1);
    reverse(f,f+n+1);reverse(g,g+m+1);
    for (int i=0;i<=m;i++) A[i]=g[i];
    for (int i=0;i<=n-m;i++) B[i]=q[i];
    pre(n+2);Ntt(A,0);Ntt(B,0);
    for (int i=0;i<t;i++)
        A[i]=1ll*A[i]*B[i]%P;
    Ntt(A,1);
    for (int i=0;i<m;i++)
        d[i]=X(f[i]-A[i]+P);
    for (int i=0;i<t;i++) A[i]=B[i]=0;
}
int main(){
    cin>>n>>m;
    for (int i=0;i<=n;i++)
        scanf("%d",&f[i]);
    for (int i=0;i<=m;i++)
        scanf("%d",&g[i]);
    dvs(f,g,q,d);
    put(q,n-m);put(d,m-1);
    return 0;
}

原文地址:https://www.cnblogs.com/xjqxjq/p/12241675.html

时间: 2024-10-06 16:35:41

多项式除法&取模的相关文章

HDU 5895 Mathematician QSC(矩阵乘法+循环节降幂+除法取模小技巧+快速幂)

传送门:HDU 5895 Mathematician QSC 这是一篇很好的题解,我想讲的他基本都讲了http://blog.csdn.net/queuelovestack/article/details/52577212 [分析]一开始想简单了,对于a^x mod p这种形式的直接用欧拉定理的数论定理降幂了 结果可想而知,肯定错,因为题目并没有保证gcd(x,s+1)=1,而欧拉定理的数论定理是明确规定的 所以得另谋出路 那么网上提供了一种指数循环节降幂的方法 具体证明可以自行从网上找一找 有

除法取模

2016.1.26 在加减乘都有公式方便我们计算时,除法显得有些丧心病狂,(a/b)%m显然不一定等于( (a%m) / (b%m) )%m. 但其实除法取模如果在算法竞赛中遇到一般都会有小技巧来避免这一步,但在这里还是说一下网上的一般处理办法. 那当然就是费马小定理. 在p为素数,b无法被p整除的情况下,有bp-1≡1(mod p) 所以(1/b)*bp-1≡(1/b)(mod p) 即bp-2≡(1/b)(mod p) 于是(a/b)%m就变成了(a*bp-2)%m 而bp-2可以用快速幂解

hdu 5407 CRB and Candies(素数筛选法,除法取模(乘法逆元))

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5407 解题思路: 官方题解: The problem is just to calculate g(N) =\ LCM(C(N,0), C(N,1), ..., C(N, N))g(N) = LCM(C(N,0),C(N,1),...,C(N,N)). Introducing function f(n) =\ LCM(1, 2, ..., n)f(n) = LCM(1,2,...,n), the

除法取模练习(51nod 1119)

题目:1119 机器人走方格 V2 思路:求C(m+n-2,n-1) % 10^9 +7       (2<=m,n<= 1000000) 在求组合数时,一般都通过双重for循环c[i][j] = c[i-1][j] + c[i-1][j-1]直接得到. 但是m,n都很大时,就会超时. 利用公式:C(n,r) = n! / r! *(n-r)!  与  a/b = x(mod M)  ->  a * (b ^ (M-2)) =x (mod M)     进行求解 费马小定理:对于素数 M

除法取模(比赛常用)

https://blog.csdn.net/qq742762377/article/details/83278688 由费马小定理可推出: (1/a)%m = a^(m-2)%m 其中m为素数. 那么, (a/b)%m 就可以变成  a * b^(m-2)%m 如果m太大,可以使用快速幂 原文地址:https://www.cnblogs.com/yuanweidao/p/11141149.html

组合数取模Lucas定理及快速幂取模

组合数取模就是求的值,根据,和的取值范围不同,采取的方法也不一样. 下面,我们来看常见的两种取值情况(m.n在64位整数型范围内) (1)  , 此时较简单,在O(n2)可承受的情况下组合数的计算可以直接用杨辉三角递推,边做加法边取模. (2) ,   ,并且是素数 本文针对该取值范围较大又不太大的情况(2)进行讨论. 这个问题可以使用Lucas定理,定理描述: 其中 这样将组合数的求解分解为小问题的乘积,下面考虑计算C(ni, mi) %p. 已知C(n, m) mod p = n!/(m!(

hdu 3037 Saving Beans 组合数取模模板题。。

Saving Beans Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2707    Accepted Submission(s): 1014 Problem Description Although winter is far away, squirrels have to work day and night to save b

[转]组合数取模 Lucas定理

对于C(n, m) mod p.这里的n,m,p(p为素数)都很大的情况.就不能再用C(n, m) = C(n - 1,m) + C(n - 1, m - 1)的公式递推了. 这里用到Lusac定理 For non-negative integers m and n and a prime p, the following congruence relation holds: where and are the base p expansions of m and n respectively.

light oj 1067 组合数取模

题目连接:http://acm.hust.edu.cn/vjudge/problem/visitOriginUrl.action?id=26784 题目: Time Limit:2000MS     Memory Limit:32768KB     64bit IO Format:%lld & %llu Description: Given n different objects, you want to take k of them. How many ways to can do it? F