首页 > 其他分享 >多项式多点求值

多项式多点求值

时间:2024-02-06 15:01:18浏览次数:26  
标签:int 多项式 分治 bl 多点 MAX 求值 prod

重点写了我认为的疑难点,若其他部分由疑问或含糊不清,欢迎提出,积极改正

题面:给一n次多项式\(F(x)\),求m个数代入的值

构造关于\(x_0\)的函数,使得代入\(x_0\)后,值为\(0\),则有\(G(x)=x-x_0\)。做多项式取模\(F(x)=Q(x)G(x)+R(x)\),\(F(x_0)=Q(x_0)G(x_0)+R(x_0)\),\(R(x_0)\)只有常数项,即答案

先分治算出\(\prod_{i=1}^{m/2}(x-x_i)\)和\(\prod_{i=m/2+1}^{m}(x-x_i)\),再分治取模。复杂度\(O(nlogn+mlog^2m)\)

进行优化,多项式除法中

\[Q_r(x)=F_r(x){G_r}^{-1}(x) \pmod {x^{n-m+1}} \]

设\(G(x)=\prod_{i=1}^m(x-x_i),G_0(x)=\prod_{i=1}^{m/2}(x-x_i),G1(x)=\prod_{i=m/2+1}^{m}(x-x_i)\)

由\(G(x)=G_0(x)G_1(x)\),得\({G_{0r}}^{-1}={G_r}^{-1}(x)G_1(x)\)

\[\begin{aligned}Q_{0r}(x)&=F_r(x){G_{0r}}^{-1}(x)\\ &=F_r(x){G_r}^{-1}(x)G_1(x)\\ &=Q(x)G_1(x) \end{aligned}\]

在分治最底层计算答案时,我们只需要常数项,系数翻转后的最高项。又由于运算在\(\pmod {x^n}\)意义下进行,我们考虑的是对n-1项贡献。分治过程中只保留最高的区间长度项,这些可能在最底层贡献最高项。

具体表现为目前区间长度为n的多项式,这一层递归会乘项数为n/2的多项式。至少n/2项才会对n-1项有贡献,现在因为砍掉前n/2项,原n-1项变为n/2-1项,则下一层长度为n/2的递归区间,考虑对n/2-1项的贡献。

流程:

  1. 分治预处理\(G_r(x)\)
  2. 求最外层逆元,算出最外层\(Q_r(x)=F_r(x){G_r}^{-1}(x)\),并保留后n项
  3. 分治计算\(Q_r(x)\),最底层最高项即常数项记为\(c_i\),这一位答案为\([x^0]F(x)-c_ix_i\)
点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int MAX=4e5+10;
#define int long long
int n,m,f[MAX],x[MAX],ans[MAX],a[MAX],b[MAX],A[MAX],bl,bc,rev[MAX],inv;
const int mod=998244353;int iG[MAX];
inline int read(){
	int x=0,f=1;char c=getchar();
	while(c>'9'||c<'0'){if(c=='-')f=-1;c=getchar();}
	while(c>='0'&&c<='9'){x=(x<<3)+(x<<1)+(c^'0');c=getchar();}
	return x*f;
}
inline void eva(int*,int*,int*,int);
signed main(){ 
	n=read();m=read();
    for(int i=0;i<=n;++i)  f[i]=read();
    for(int i=1;i<=m;++i)  x[i]=read();
    eva(f,x,ans,max(n,m));
    for(int i=1;i<=m;++i)  printf("%lld\n",ans[i]);
}
int *g[MAX<<2],*h[MAX<<2],bin[MAX<<6],*np(bin);
inline int power(int a,int b){
    int res=1;
    while(b){
        if(b&1)  res=res*a%mod;
        a=a*a%mod;b>>=1;
    }return res;
}inline void work(int n){
    bl=1;bc=0;
    while(bl<=n)  bl<<=1,++bc;
    for(int i=0;i<bl;++i)
        rev[i]=(rev[i>>1]>>1)|((i&1)<<bc-1);
}inline void NTT(int *a,int n,int op){
    for(int i=0;i<n;++i)
        if(i<rev[i])  swap(a[i],a[rev[i]]);
    for(int i=1;i<n;i<<=1){
        int wn=power(3,(op*(mod-1)/(i<<1)+mod-1)%(mod-1));
        for(int j=0;j<n;j+=i<<1){
            int w=1;
            for(int k=0;k<i;++k){
                int x=a[j+k],y=w*a[j+k+i]%mod;
                a[j+k]=(x+y)%mod;a[j+k+i]=(x-y+mod)%mod;
                w=w*wn%mod;
            }
        }
    }if(op==-1){
        inv=power(n,mod-2);
        for(int i=0;i<n;++i)  a[i]=a[i]*inv%mod;
    }
}inline void mul(int *f,int *g,int *c,int n){
    work(n<<1);
    for(int i=0;i<n;++i)  a[i]=f[i],b[i]=g[i];
    for(int i=n;i<bl;++i)  a[i]=b[i]=0;
    NTT(a,bl,1);NTT(b,bl,1);
    for(int i=0;i<bl;++i)  a[i]=a[i]*b[i]%mod;
    NTT(a,bl,-1);
    for(int i=0;i<n;++i)  c[i]=a[i];
}void solve(int *f,int *g,int n){
    if(n==1){g[0]=power(f[0],mod-2);return;}
    solve(f,g,n>>1);work(n);
    for(int i=0;i<n;++i)  a[i]=f[i],b[i]=g[i];
    for(int i=n;i<bl;++i)  a[i]=b[i]=0;
    NTT(a,bl,1);NTT(b,bl,1);
    for(int i=0;i<bl;++i)  a[i]=a[i]*b[i]%mod*b[i]%mod;
    NTT(a,bl,-1);
    for(int i=0;i<n;++i)  g[i]=(2*g[i]-a[i]+mod)%mod;
}
void solve1(int pos,int l,int r){
    g[pos]=np;np+=(r-l+2)*2;h[pos]=np;np+=(r-l+2)*2;
    if(l==r){g[pos][0]=1;g[pos][1]=(mod-x[l])%mod;return;}
    int mid=l+r>>1;solve1(pos<<1,l,mid);solve1(pos<<1|1,mid+1,r);
    mul(g[pos<<1],g[pos<<1|1],g[pos],r-l+2);
}void solve2(int pos,int l,int r,int *ans){
    if(l==r){ans[l]=h[pos][0];return;}
    int mid=l+r>>1;
    reverse(g[pos<<1|1],g[pos<<1|1]+r-mid+1);
    mul(h[pos],g[pos<<1|1],A,r-l+1);
    for(int i=0;i<mid-l+1;++i)  h[pos<<1][i]=A[(r-mid)+i];
    solve2(pos<<1,l,mid,ans);
    reverse(g[pos<<1],g[pos<<1]+mid-l+2);
    mul(h[pos],g[pos<<1],A,r-l+1);
    for(int i=0;i<r-mid;++i)  h[pos<<1|1][i]=A[(mid-l+1)+i];
    solve2(pos<<1|1,mid+1,r,ans);
}inline void eva(int *a,int *b,int *c,int n){
    solve1(1,1,n);int M=1;while(M<=n)  M<<=1;
    solve(g[1],iG,M);
    for(int i=0;i<=n;++i)  A[i]=f[n-i];
    mul(A,iG,A,n+n+1);reverse(A,A+n+n+1);
    for(int i=0;i<n;++i)  h[1][i]=A[n+1+i];
    solve2(1,1,n,c);
    for(int i=1;i<=n;++i)  c[i]=(a[0]+c[i]*b[i])%mod;
}

标签:int,多项式,分治,bl,多点,MAX,求值,prod
From: https://www.cnblogs.com/yswn/p/18009763

相关文章

  • (11/60)有效的括号、删除字符串中所有相邻重复项、逆波兰表达式求值
    有效的括号leetcode:20.有效的括号实现思路遍历到左括号,入栈对应的右括号(方便遍历到右括号时进行对比);遍历到右括号,对比栈顶元素。把无效三种情况照顾到:1.左括号多了(遍历结束后栈不为空);2.左右括号不匹配(右括号时栈顶元素与当前元素对比);3.右括号多了(右括号时栈是空的)。复......
  • 代码随想录算法训练营第十一天 | 20. 有效的括号 | 1047. 删除字符串中的所有相邻重
     有效的括号 已解答简单 相关标签相关企业 提示 给定一个只包括 '(',')','{','}','[',']' 的字符串 s ,判断字符串是否有效。有效字符串需满足:左括号必须用相同类型的右括号闭合。左括号必须以正确的顺序闭合。每个右括号都有一个对应......
  • 多项式学习笔记
    多项式学习笔记泰勒展开有\(F(x)=F(x_{0})+\frac{F'(x_{0})}{1!}(x-x_{0})+\frac{F'(x_{0})}{2!}(x-x_{0})^{2}\cdots+\frac{F^{(n)}(x_{0})}{n!}(x-x_{0})^{n}\)给定\(G(x)\)求解\(G(F(x))\equiv0\bmodx^{n}\)的\(F(x)\)。考虑分治:设\(f_{0}(x)\)是$G(F(......
  • 代码随想录算法训练营第十一天| 20. 有效的括号 1047. 删除字符串中的所有相邻重复
    20.有效的括号 给定一个只包括 '(',')','{','}','[',']' 的字符串 s ,判断字符串是否有效。有效字符串需满足:左括号必须用相同类型的右括号闭合。左括号必须以正确的顺序闭合。每个右括号都有一个对应的相同类型的左括号。题目链接:20.有效的括号-力扣(LeetCode)思路:只......
  • 萌新的多项式学习笔记(板子)
    萌新的多项式学习笔记(板子)详细讲解FFT直接放板子structcp{ doublex,y; cp(doublexx=0,doubleyy=0){x=xx,y=yy;}};intr[maxn];cpoperator+(constcp&a,constcp&b){returncp(a.x+b.x,a.y+b.y);}cpoperator-(constcp&a,constcp&b){returncp(a.x-b.x,a......
  • R语言非线性方程数值分析生物降解、植物生长数据:多项式、渐近回归、负指数方程、幂函
    全文链接:https://tecdat.cn/?p=33742原文出处:拓端数据部落公众号简介在选择最佳拟合实验数据的方程时,可能需要一些经验。当我们没有文献信息时该怎么办?我们建立模型的方法通常是经验主义的。也就是说,我们观察过程,绘制数据并注意到它们遵循一定的模式。例如,我们的客户可能观察......
  • 多项式
    很多证明需要用到积分知识,所以只有结论和代码一、多项式求导$F'(x)=\sum_{i=0}a_{i+1}\times(i+1)x$点击查看代码inlinevoiddao(int*g,int*f){for(inti=0;i<n;++i)g[i]=f[i+1]*(i+1)%mod;}二、多项式求积分求导逆运算$F'(x)=\sum_{i=1}a_{i-1}\times\fr......
  • P7324 [WC2021] 表达式求值 题解
    题目链接点击打开链接题目解法不错的题首先建出表达式树说实话我一开始不知道怎么建,但看了代码之后就懂了这里简单说一下:假如要对区间\([l,r]\)建树,分\(E_r=)\)和\(E_r\neq)\)的情况\(E_r=)\),找到匹配的左括号,递归下去建树\(E_r\neq)\),\(r\)可以作为单独的一个......
  • 【模板】多项式半家桶 version 2
    #include<bits/stdc++.h>usingnamespacestd;#ifdefLOCAL#definedebug(...)fprintf(stderr,##__VA_ARGS__)#else#defineendl"\n"#definedebug(...)void(0)#endiftypedeflonglongLL;template<unsignedumod>structmodint{......
  • 我的多项式全家桶
    第一个自己实现的多项式全家桶。打比赛时终于有板子了!代码是从之前学转置原理的那篇博客里升级来的。但是功能很残?效率很逊?接口很怪?评价是能用就行。目前封装了:乘、逆、除(取模)、开方(无二次剩余,不会qwq)、对数、指数、多点求值、快速插值、常系数齐次线性递推、Berlekamp-Massey......