多项式除法例子_方程除法怎么算

多项式除法例子_方程除法怎么算问题描述给定一个$n$次多项式$F(x)$和一个$m$次多项式$G(x)$,请求出多项式$Q(x)$,$R(x)$,满足以下条件:$Q(x)$次数为$n-m$,$R(x)$次数

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

问题描述

给定一个 $n$次多项式 $F(x)$ 和一个 $m$ 次多项式 $G(x)$,请求出多项式 $Q(x)$,$R(x)$,满足以下条件:

  • $Q(x)$ 次数为 $n-m$,$R(x)$ 次数小于 $m$
  • $F(x) = Q(x) * G(x) + R(x)$

所有运算在模998244353意义下进行

详见洛谷 P4512

分析

具体来说,设多项式$A$为$n$次多项式,考虑一种操作$R$,使得

$\displaystyle A_R(x)=x^n A(\frac{1}{x})$

稍微想象一下,可以发现$A_R[i]=A[n-i]$($[i]$表示多项式的第$i$次系数)。

这个操作可以$O(n)$完成。

然后开始化式子。

$$F(x)=Q(x) * G(x)+R(x)$$

$$\displaystyle F(\frac{1}{x})=Q(\frac{1}{x}) * G(\frac{1}{x})+R(\frac{1}{x})$$

$$\displaystyle x^n F(\frac{1}{x})=x^{n-m} Q(\frac{1}{x}) * x^m G(\frac{1}{x})+x^{n-m+1} * x^{m-1} R(\frac{1}{x})$$

$$\displaystyle F_R(x)=Q_R(x)*G_R(x)+x^{n-m+1} * R_R(x)$$

$$\displaystyle F_R(x) \equiv Q_R(x)*G_R(x)\pmod {x^{n-m+1}}$$

$$\displaystyle Q_R(x) \equiv F_R(x)*G_R^{-1}(x)\pmod {x^{n-m+1}}$$

求一遍$G_R$的逆,然后就可以利用多项式乘法求出$Q$。然后

$$R(x)=F(x)-G(x)*Q(x)$$

直接计算即可。系数翻转可以用自带的 $reverse$ 函数,逆元最好迭代求解

总的时间复杂度$O(nlogn)$。

代码:

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
const int N = 1<<20;

int read()
{
    int x = 0, f = 1; char c = getchar();
    while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();}
    while(c >= '0' && c <= '9') x = (x<<1) + (x<<3) + c - '0', c = getchar();
    return x * f;
}
namespace Polynomial
{
    const ll P = 998244353, g = 3, gi = 332748118;
    static int rev[N];
    int lim, bit;
    ll add(ll a, ll b)
    {
        return (a += b) >= P ? a - P : a;
    }
    ll qpow(ll a, ll b)
    {
        ll prod = 1;
        while(b)
        {
            if(b & 1) prod = prod * a % P;
            a = a * a % P;
            b >>= 1;
        }
        return (prod + P) % P;
    }
    void calrev() {
        for(int i = 1; i < lim; i++)
            rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << (bit - 1));
    }
    void NTT(ll *A, int inv)
    {
        for(int i = 0; i < lim; i++)
            if(i < rev[i]) swap(A[i], A[rev[i]]);
        for(int mid = 1; mid < lim; mid <<= 1)
        {
            ll tmp = qpow(inv == 1 ? g : gi, (P - 1) / (mid << 1));
            for(int j = 0; j < lim; j += (mid << 1))
            {
                ll omega = 1;
                for(int k = 0; k < mid; k++, omega = (omega * tmp) % P) {
                    int x = A[j + k], y = omega * A[j + k + mid] % P;
                    A[j + k] = (x + y) % P;
                    A[j + k + mid] = (x - y + P) % P;
                }
            }
        }
        if(inv == 1) return;
        int invn = qpow(lim, P - 2);
        for(int i = 0; i < lim; i++)
            A[i] = A[i] * invn % P;
    }
    static ll x[N], y[N];
    void mul(ll *a, ll *b)
    {
        memset(x, 0, sizeof x);
        memset(y, 0, sizeof y);
        for(int i = 0; i < (lim >> 1); i++)
            x[i] = a[i], y[i] = b[i];
        NTT(x, 1), NTT(y, 1);
        for(int i = 0; i < lim; i++)
            x[i] = x[i] * y[i] % P;
        NTT(x, -1);
        for(int i = 0; i < lim; i++)
            a[i] = x[i];
    }
    static ll c[2][N];
    void Inv(ll *a, int n)
    {
        int p = 0;
        memset(c, 0, sizeof c);
        c[0][0] = qpow(a[0], P - 2);
        lim = 2, bit = 1;
        while(lim <= (n << 1))
        {
            lim <<= 1, bit++;
            calrev();
            p ^= 1;
            memset(c[p], 0, sizeof c[p]);
            for(int i = 0; i <= lim; i++)
                c[p][i] = add(c[p^1][i], c[p^1][i]);
            mul(c[p^1], c[p^1]);
            mul(c[p^1], a);
            for(int i = 0; i <= lim; i++)
                c[p][i] = add(c[p][i], P - c[p^1][i]);
        }
        for(int i = 0; i < lim; i++)
            a[i] = c[p][i];
    }
}
using namespace Polynomial;
int n,  m;
ll F[N], G[N], Q[N], R[N], Gr[N];
int main()
{
    n = read(), m = read();
    for(int i = 0; i <= n; i++)
        F[i] = read(), Q[n - i] = F[i];
    for(int i = 0; i <= m; i++)
        G[i] = read(), Gr[m - i] = G[i];
    for(int i = n - m + 2; i <= m; i++)
        Gr[i] = 0;
    Inv(Gr, n - m + 1);    //Gr=Gr的逆
    mul(Q, Gr);            //Q=Q*Gr
    reverse(Q, Q + n - m + 1);   //Q=reverse(Q)
    for(int i = n - m + 1; i <= n; i++)
        Q[i] = 0;
    for(int i = 0; i <= n - m; i++)
        printf("%lld ", Q[i]);
    printf("\n");
    lim = 1, bit = 0;
    while(lim <= (n << 2))
        lim <<= 1, bit++;
    calrev();
    mul(Q, G);
    for(int i = 0; i < m; i++)
        printf("%lld ", add(F[i], P - Q[i]));   //R=F - Q*G
    return 0;
}

 

代码转载自:https://www.luogu.org/blog/AKIOIorz/p4512-mu-ban-duo-xiang-shi-chu-fa

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/167859.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • Qt框架简介

    Qt框架简介这里的Qt不是指Qt语音平台,而是指GUI框架。截止至2019年12月,Qt的最新版本是5.14.0,但仍有很多资料是基于Qt4,为了避免大家误入歧途,所以写了这篇文章。Qt一开始是由奇趣公司开发的,后来被Nokia收购了,然后再被Digia收购了。所以有的人会误以为Qt就是为了塞班系统而生,是个落伍的产物。但是很多嵌入式软件、桌面工具都是用Qt来开发的,包括Quartus和Caden…

    2022年5月16日
    978
  • 流媒体服务器配置_视频监控流媒体服务器配置

    流媒体服务器配置_视频监控流媒体服务器配置对于普通视频网站来说,并发数量是一个非常有参考价值的数据,在部分时间段,并发数量也许不大,但是也可能短时间内暴涨且没有上限,此时就需要系统具备良好的扩张能力和负载均衡能力。那么如何针对流媒体服务器分发的RTSP流进行并发压力测试了解系统的能力?本分和大家分享一下我们的测试过程。通过使用多路RTSP客户端进行拉流,即可达到并发压力测试。对于RTSP客户端的选择,可以选择开源的OpenRTSP客户端进行拉流测试。OpenRTSP的使用方法如下:1、下载源码wgethttp://www.live5

    2022年10月20日
    4
  • python 元类编程_Python进阶

    python 元类编程_Python进阶前言通常我们创建类都是使用class类名,但是小伙伴们有没有想过,类是由谁来创建的呢,python中常说的万物皆对象,对象是由类创建的,那类本身也可以看做是对象,类可以由元类type创建type

    2022年7月31日
    7
  • vim中复制粘贴快捷键_保存到剪贴板的截图去哪里找

    vim中复制粘贴快捷键_保存到剪贴板的截图去哪里找gg定位到第一行,V选中光标所在行,G定位到文件末尾Ctrl+ACtrl+C全选复制:map&lt;C-A&gt;&lt;Esc&gt;ggVGyCtrl+ACtrl+xq剪切:map&lt;C-X&gt;&lt;Esc&gt;ggVGdCtrl+v粘贴:map&lt;C-V&gt;&lt;Esc&gt;p…

    2022年9月22日
    1
  • 用c语言实现顺序表_顺序表代码讲解以及实现

    用c语言实现顺序表_顺序表代码讲解以及实现一、学习内容:1、创建顺序表2、按数值查找3、按位置查找4、插入一个数值5、删除一个数值6、销毁顺序表7、求前驱算法8、求后继算法

    2025年6月3日
    5
  • pytorch mseloss_pytorch中文手册

    pytorch mseloss_pytorch中文手册1、均方差损失函数loss,x,y可以是向量或者矩阵,i是下标。很多的loss函数都有size_average和reduce两个布尔类型的参数。因为一般损失函数都是直接计算batch的数据,因此返回的loss结果都是维度为(batch_size,)的向量。(说的是一般的情况,这里返回的没有维度为(batch_size,)这种情况)2、nn.MSELoss()参数介绍(1)如果reduction=‘none’,直接返回向量形式的loss(2)如果redu

    2022年9月17日
    2

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号